165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane/* 265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane * Copyright (C) 2014 The Android Open Source Project 365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane * 465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane * Licensed under the Apache License, Version 2.0 (the "License"); 565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane * you may not use this file except in compliance with the License. 665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane * You may obtain a copy of the License at 765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane * 865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane * http://www.apache.org/licenses/LICENSE-2.0 965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane * 1065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane * Unless required by applicable law or agreed to in writing, software 1165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane * distributed under the License is distributed on an "AS IS" BASIS, 1265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane * See the License for the specific language governing permissions and 1465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane * limitations under the License. 1565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane */ 1665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 1765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lanepackage com.android.tv.settings.dialog; 1865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 1965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Laneimport android.animation.Animator; 2065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Laneimport android.animation.AnimatorListenerAdapter; 2165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Laneimport android.animation.ObjectAnimator; 2265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Laneimport android.content.Context; 2365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Laneimport android.content.Intent; 2465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Laneimport android.content.res.Resources; 2565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Laneimport android.database.DataSetObserver; 2665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Laneimport android.graphics.Bitmap; 2765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Laneimport android.graphics.drawable.Drawable; 2865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Laneimport android.media.AudioManager; 2965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Laneimport android.net.Uri; 3065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Laneimport android.os.Handler; 3165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Laneimport android.os.Looper; 3265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Laneimport android.support.v17.leanback.R; 3365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Laneimport android.support.v7.widget.RecyclerView; 3465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Laneimport android.support.v7.widget.RecyclerView.ViewHolder; 3565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Laneimport android.text.TextUtils; 3665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Laneimport android.util.Log; 3765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Laneimport android.util.TypedValue; 3865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Laneimport android.view.KeyEvent; 3965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Laneimport android.view.LayoutInflater; 4065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Laneimport android.view.View; 4165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Laneimport android.view.ViewGroup; 4265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Laneimport android.view.WindowManager; 4365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Laneimport android.view.animation.DecelerateInterpolator; 4465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Laneimport android.view.animation.Interpolator; 4565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Laneimport android.widget.AdapterView.OnItemSelectedListener; 4665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Laneimport android.widget.ImageView; 4765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Laneimport android.widget.TextView; 4865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 4965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Laneimport com.android.tv.settings.dialog.Layout; 5065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 5165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Laneimport java.security.InvalidParameterException; 5265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Laneimport java.util.ArrayList; 5365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 5465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane/** 5565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane * Adapter class which creates actions. 5665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane */ 5765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Laneclass SettingsLayoutAdapter extends RecyclerView.Adapter { 5865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane private static final String TAG = "SettingsLayoutAdapter"; 5965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane private static final boolean DEBUG = false; 6065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane private static final DecelerateInterpolator ALPHA_DECEL = new DecelerateInterpolator(2F); 6165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane private final Handler mRefreshViewHandler = new Handler(Looper.getMainLooper()); 6265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 6365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane /** 6465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane * Object listening for adapter events. 6565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane */ 6665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane public interface Listener { 6765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 6865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane /** 6965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane * Called when the user clicks on an action. 7065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane */ 7165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane public void onRowClicked(Layout.LayoutRow item); 7265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 7365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 7465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane public interface OnFocusListener { 7565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 7665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane /** 7765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane * Called when the user focuses on an action. 7865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane */ 7965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane public void onActionFocused(Layout.LayoutRow item); 8065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 8165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 8265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane private final ActionOnKeyPressAnimator mActionOnKeyPressAnimator; 8365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane private final ActionOnFocusAnimator mActionOnFocusAnimator; 8465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane private LayoutInflater mInflater; 8565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane private ArrayList<Layout.LayoutRow> mLayoutRows; 8665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane private Listener mListener; 8765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane private boolean mNoAnimateMode = false; 8801a5b81394670c6c5c2011673ed48c4fee1cf77bbulic private boolean mFocusListenerEnabled = true; 8965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 9065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane private final View.OnClickListener mOnClickListener = new View.OnClickListener() { 9165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane @Override 9265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane public void onClick(View v) { 9365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane if (v != null && v.getWindowToken() != null && mListener != null) { 9465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane mListener.onRowClicked(((LayoutRowViewHolder) v.getTag(R.id.action_title)). 9565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane getLayoutRow()); 9665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 9765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 9865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane }; 9965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 10065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane public SettingsLayoutAdapter(Listener listener, OnFocusListener onFocusListener) { 10165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane super(); 10265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane mListener = listener; 10365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane mActionOnKeyPressAnimator = new ActionOnKeyPressAnimator(listener); 10465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane mActionOnFocusAnimator = new ActionOnFocusAnimator(onFocusListener); 10565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 10665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 10765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane public void setLayoutRows(ArrayList<Layout.LayoutRow> layoutRows) { 10865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane mLayoutRows = layoutRows; 10965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 11065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 11165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane public void setNoAnimateMode() { 11265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane mNoAnimateMode = true; 11365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 11465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 11501a5b81394670c6c5c2011673ed48c4fee1cf77bbulic public void setFocusListenerEnabled(boolean enabled) { 11601a5b81394670c6c5c2011673ed48c4fee1cf77bbulic mFocusListenerEnabled = enabled; 11701a5b81394670c6c5c2011673ed48c4fee1cf77bbulic } 11801a5b81394670c6c5c2011673ed48c4fee1cf77bbulic 11965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane @Override 12065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane public int getItemViewType(int position) { 12165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane return mLayoutRows.get(position).getViewType(); 12265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 12365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 12465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane @Override 12565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { 12665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane if (mInflater == null) { 12765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane mInflater = (LayoutInflater) parent.getContext().getSystemService( 12865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane Context.LAYOUT_INFLATER_SERVICE); 12965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 13065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane View v = null; 13165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane switch (viewType) { 13265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane case Layout.LayoutRow.VIEW_TYPE_ACTION: 13365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane v = mInflater.inflate(R.layout.lb_dialog_action_list_item, parent, false); 13465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane break; 13565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane case Layout.LayoutRow.VIEW_TYPE_STATIC: 13665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane v = mInflater.inflate(R.layout.lb_dialog_static_list_item, parent, false); 13765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane break; 13865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 13965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane v.setTag(R.layout.lb_dialog_action_list_item, parent); 14065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane LayoutRowViewHolder viewHolder = new LayoutRowViewHolder(v, mActionOnKeyPressAnimator, 14165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane mActionOnFocusAnimator, mOnClickListener); 14265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane viewHolder.init(viewType); 14365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane return viewHolder; 14465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 14565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 14665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane @Override 14765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane public void onBindViewHolder(RecyclerView.ViewHolder baseHolder, int position) { 14865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane LayoutRowViewHolder holder = (LayoutRowViewHolder) baseHolder; 14965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane if (position < mLayoutRows.size()) { 15065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane holder.bind(mLayoutRows.get(position)); 15165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 15265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 15365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 15465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane @Override 15565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane public int getItemCount() { 15665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane return mLayoutRows.size(); 15765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 15865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 15965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane public void setListener(Listener listener) { 16065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane mListener = listener; 16165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane mActionOnKeyPressAnimator.setListener(listener); 16265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 16365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 16465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane public void setOnFocusListener(OnFocusListener onFocusListener) { 16565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane mActionOnFocusAnimator.setOnFocusListener(onFocusListener); 16665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 16765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 16865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane public void registerDataSetObserver(DataSetObserver dataSetObserver) { 16965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 17065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 17165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane public void setOnItemSelectedListener(OnItemSelectedListener listener) { 17265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 17365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 17465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane private class LayoutRowViewHolder extends ViewHolder implements 17565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane Layout.ContentNodeRefreshListener { 17665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 17765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane private class RefreshDescription implements Runnable { 17865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane public String mDescriptionText; 17965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 18065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane @Override 18165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane public void run() { 18265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane mDescription.setText(mDescriptionText); 18365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 18465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 18565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 18665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane private final ActionOnKeyPressAnimator mActionOnKeyPressAnimator; 18765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane private final ActionOnFocusAnimator mActionOnFocusAnimator; 18865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane private final View.OnClickListener mViewOnClickListener; 18965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane private Layout.LayoutRow mLayoutRow; 19065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane private TextView mDescription = null; 19165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane private TextView mTitle; 19265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane private ImageView mCheckmarkView; 19365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane private ImageView mIndicatorView; 19465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane private View mContent; 19565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane private ImageView mChevronView; 19665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane private int mViewType; 19765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane private RefreshDescription mRefreshDescription; 19865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 19965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane public LayoutRowViewHolder(View v, ActionOnKeyPressAnimator actionOnKeyPressAnimator, 20065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane ActionOnFocusAnimator actionOnFocusAnimator, 20165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane View.OnClickListener viewOnClickListener) { 20265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane super(v); 20365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane mActionOnKeyPressAnimator = actionOnKeyPressAnimator; 20465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane mActionOnFocusAnimator = actionOnFocusAnimator; 20565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane mViewOnClickListener = viewOnClickListener; 20665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 20765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 20865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane public Layout.LayoutRow getLayoutRow() { 20965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane return mLayoutRow; 21065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 21165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 21265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane public void init(int viewType) { 21365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane mViewType = viewType; 21465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane mTitle = (TextView) itemView.findViewById(R.id.action_title); 21565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane if (mViewType == Layout.LayoutRow.VIEW_TYPE_ACTION) { 21665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane mDescription = (TextView) itemView.findViewById(R.id.action_description); 21765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 21865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane mCheckmarkView = (ImageView) itemView.findViewById(R.id.action_checkmark); 21965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane mIndicatorView = (ImageView) itemView.findViewById(R.id.action_icon); 22065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane mContent = itemView.findViewById(R.id.action_content); 22165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane mChevronView = (ImageView) itemView.findViewById(R.id.action_next_chevron); 22265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane itemView.setTag(R.id.action_title, this); 22365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane itemView.setOnKeyListener(mActionOnKeyPressAnimator); 22465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane itemView.setOnClickListener(mViewOnClickListener); 22565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane itemView.setOnFocusChangeListener(mActionOnFocusAnimator); 22665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 22765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 22865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane //TODO need to create separate xxxViewHolder classes to eliminate tests of "mViewType". 22965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane public void onRefreshView() { 23065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane if (mViewType == Layout.LayoutRow.VIEW_TYPE_ACTION) { 23165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane Layout.StringGetter description = mLayoutRow.getDescription(); 23265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane if (description != null) { 23365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane String text = description.get(); 23465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane if (!TextUtils.equals(mRefreshDescription.mDescriptionText, text)) { 23565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane mRefreshDescription.mDescriptionText = text; 23665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane mRefreshViewHandler.removeCallbacks(mRefreshDescription); 23765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane mRefreshViewHandler.post(mRefreshDescription); 23865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 23965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 24065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 24165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 24265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 24365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane public void bind(Layout.LayoutRow layoutRow) { 24465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane mLayoutRow = layoutRow; 24565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane if (mViewType != layoutRow.getViewType()) { 24665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane throw new InvalidParameterException("view type does not match"); 24765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 24865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 24965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane if (mViewType == Layout.LayoutRow.VIEW_TYPE_ACTION) { 25065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane Layout.StringGetter description = layoutRow.getDescription(); 25165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane if (description != null) { 25265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane mRefreshDescription = new RefreshDescription(); 25365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane String text = description.get(); 25465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane mDescription.setText(text); 25565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane mRefreshDescription.mDescriptionText = text; 25665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane mDescription.setVisibility(View.VISIBLE); 25765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane description.setListener(this); 25865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } else { 25965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane mDescription.setVisibility(View.GONE); 26065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 26165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 26265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 26365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane mTitle.setText(layoutRow.getTitle()); 26465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane mCheckmarkView.setVisibility(layoutRow.isChecked() ? View.VISIBLE : View.INVISIBLE); 26565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 26665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane ViewGroup.LayoutParams contentLp = mContent.getLayoutParams(); 26765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane if (setIndicator(mIndicatorView, layoutRow)) { 26865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane contentLp.width = itemView.getContext().getResources() 26965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane .getDimensionPixelSize(R.dimen.lb_action_text_width); 27065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } else { 27165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane contentLp.width = itemView.getContext().getResources() 27265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane .getDimensionPixelSize(R.dimen.lb_action_text_width_no_icon); 27365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 27465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane mContent.setLayoutParams(contentLp); 27565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 27665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane mChevronView.setVisibility(layoutRow.hasNext() ? View.VISIBLE : View.INVISIBLE); 27765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 27865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane final Resources res = itemView.getContext().getResources(); 27965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane if (layoutRow.hasMultilineDescription()) { 28065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane mTitle.setMaxLines(res.getInteger(R.integer.lb_dialog_action_title_max_lines)); 28165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane if (mViewType == Layout.LayoutRow.VIEW_TYPE_ACTION) { 28265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane mDescription.setMaxHeight( 28365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane getDescriptionMaxHeight(itemView.getContext(), mTitle)); 28465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 28565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } else { 28665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane mTitle.setMaxLines(res.getInteger(R.integer.lb_dialog_action_title_min_lines)); 28765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane if (mViewType == Layout.LayoutRow.VIEW_TYPE_ACTION) { 28865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane mDescription.setMaxLines( 28965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane res.getInteger(R.integer.lb_dialog_action_description_min_lines)); 29065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 29165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 29265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 29365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane mActionOnFocusAnimator.unFocus(itemView); 29465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 29565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 29665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane private boolean setIndicator(final ImageView indicatorView, Layout.LayoutRow action) { 29765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 29865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane Context context = indicatorView.getContext(); 29965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane Drawable indicator = action.getIcon(); 30065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane if (indicator != null) { 30165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane indicatorView.setImageDrawable(indicator); 30265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane indicatorView.setVisibility(View.VISIBLE); 30365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } else { 30465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane Uri iconUri = action.getIconUri(); 30565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane if (iconUri != null) { 30665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane indicatorView.setVisibility(View.INVISIBLE); 30765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } else { 30865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane indicatorView.setVisibility(View.GONE); 30965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane return false; 31065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 31165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 31265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane return true; 31365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 31465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 31565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane private void fadeIn(View v) { 31665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane ObjectAnimator alphaAnimator = ObjectAnimator.ofFloat(v, "alpha", 0f, 1f); 31765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane alphaAnimator.setDuration( 31865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane v.getContext().getResources().getInteger( 31965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane android.R.integer.config_mediumAnimTime)); 32065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane alphaAnimator.start(); 32165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 32265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 32365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane /** 32465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane * @return the max height in pixels the description can be such that the 32565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane * action nicely takes up the entire screen. 32665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane */ 32765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane private int getDescriptionMaxHeight(Context context, TextView title) { 32865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane final Resources res = context.getResources(); 32965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane final float verticalPadding = 33065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane res.getDimension(R.dimen.lb_dialog_list_item_vertical_padding); 33165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane final int titleMaxLines = res.getInteger(R.integer.lb_dialog_action_title_max_lines); 33265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane final int displayHeight = ((WindowManager) context.getSystemService( 33365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane Context.WINDOW_SERVICE)).getDefaultDisplay().getHeight(); 33465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 33565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane // The 2 multiplier on the title height calculation is a 33665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane // conservative estimate for font padding which can not be 33765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane // calculated at this stage since the view hasn't been rendered yet. 33865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane return (int) (displayHeight - 33965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 2 * verticalPadding - 2 * titleMaxLines * title.getLineHeight()); 34065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 34165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 34265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 34365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 34465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane private class ActionOnFocusAnimator implements View.OnFocusChangeListener { 34565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 34665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane private boolean mResourcesSet; 34765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane private float mUnselectedAlpha; 34865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane private float mSelectedTitleAlpha; 34965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane private float mDisabledTitleAlpha; 35065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane private float mSelectedDescriptionAlpha; 35165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane private float mDisabledDescriptionAlpha; 35265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane private float mUnselectedDescriptionAlpha; 35365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane private float mSelectedChevronAlpha; 35465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane private float mDisabledChevronAlpha; 35565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane private int mAnimationDuration; 35665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane private OnFocusListener mOnFocusListener; 35765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane private View mSelectedView; 35865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 35965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane ActionOnFocusAnimator(OnFocusListener onFocusListener) { 36065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane mOnFocusListener = onFocusListener; 36165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 36265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 36365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane public void setOnFocusListener(OnFocusListener onFocusListener) { 36465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane mOnFocusListener = onFocusListener; 36565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 36665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 36765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane public void unFocus(View v) { 36865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane changeFocus((v != null) ? v : mSelectedView, false, false); 36965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 37065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 37165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane @Override 37265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane public void onFocusChange(View v, boolean hasFocus) { 37365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane if (hasFocus) { 37465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane mSelectedView = v; 37565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane if (mNoAnimateMode) { 37665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane mNoAnimateMode = false; 37765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane changeFocus(v, true /* hasFocus */, false /* shouldAnimate */); 37865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } else { 37965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane changeFocus(v, true /* hasFocus */, true /* shouldAnimate */); 38001a5b81394670c6c5c2011673ed48c4fee1cf77bbulic if (mOnFocusListener != null && mFocusListenerEnabled) { 38165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane // We still call onActionFocused so that listeners can clear state if they 38265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane // want. 38365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane mOnFocusListener.onActionFocused( 38465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane ((LayoutRowViewHolder) v.getTag(R.id.action_title)).getLayoutRow()); 38565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 38665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 38765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } else { 38865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane if (mSelectedView == v) { 38965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane mSelectedView = null; 39065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 39165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane changeFocus(v, false /* hasFocus */, true /* shouldAnimate */); 39265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 39365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 39465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 39565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane private void changeFocus(View v, boolean hasFocus, boolean shouldAnimate) { 39665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane if (v == null) { 39765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane return; 39865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 39965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 40065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane if (!mResourcesSet) { 40165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane mResourcesSet = true; 40265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane final Resources res = v.getContext().getResources(); 40365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 40465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane mAnimationDuration = res.getInteger(R.integer.lb_dialog_animation_duration); 40565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 40665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane mUnselectedAlpha = 40765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane getFloat(res, R.string.lb_dialog_list_item_unselected_text_alpha); 40865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 40965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane mSelectedTitleAlpha = 41065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane getFloat(res, R.string.lb_dialog_list_item_selected_title_text_alpha); 41165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane mDisabledTitleAlpha = 41265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane getFloat(res, R.string.lb_dialog_list_item_disabled_title_text_alpha); 41365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 41465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane mSelectedDescriptionAlpha = 41565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane getFloat(res, R.string.lb_dialog_list_item_selected_description_text_alpha); 41665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane mUnselectedDescriptionAlpha = getFloat(res, 41765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane R.string.lb_dialog_list_item_unselected_description_text_alpha); 41865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane mDisabledDescriptionAlpha = 41965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane getFloat(res, R.string.lb_dialog_list_item_disabled_description_text_alpha); 42065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 42165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane mSelectedChevronAlpha = getFloat(res, 42265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane R.string.lb_dialog_list_item_selected_chevron_background_alpha); 42365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane mDisabledChevronAlpha = getFloat(res, 42465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane R.string.lb_dialog_list_item_disabled_chevron_background_alpha); 42565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 42665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 42765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane Layout.LayoutRow layoutRow = 42865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane ((LayoutRowViewHolder) v.getTag(R.id.action_title)).getLayoutRow(); 42965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 43065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane float titleAlpha; 43165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane if (layoutRow.isEnabled() && !layoutRow.infoOnly()) { 43265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane titleAlpha = hasFocus ? mSelectedTitleAlpha : mUnselectedAlpha; 43365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } else { 43465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane titleAlpha = mDisabledTitleAlpha; 43565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 43665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane float descriptionAlpha; 43765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane if (!hasFocus || layoutRow.infoOnly()) { 43865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane descriptionAlpha = mUnselectedDescriptionAlpha; 43965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } else { 44065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane descriptionAlpha = layoutRow.isEnabled() ? mSelectedDescriptionAlpha : 44165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane mDisabledDescriptionAlpha; 44265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 44365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane float chevronAlpha; 44465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane if (layoutRow.hasNext() && !layoutRow.infoOnly()) { 44565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane chevronAlpha = 44665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane layoutRow.isEnabled() ? mSelectedChevronAlpha : mDisabledChevronAlpha; 44765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } else { 44865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane chevronAlpha = 0; 44965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 45065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 45165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane TextView title = (TextView) v.findViewById(R.id.action_title); 45265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane setAlpha(title, shouldAnimate, titleAlpha); 45365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 45465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane TextView description = (TextView) v.findViewById(R.id.action_description); 45565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane if (description != null) { 45665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane setAlpha(description, shouldAnimate, descriptionAlpha); 45765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 45865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 45965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane ImageView checkmark = (ImageView) v.findViewById(R.id.action_checkmark); 46065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane setAlpha(checkmark, shouldAnimate, titleAlpha); 46165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 46265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane ImageView icon = (ImageView) v.findViewById(R.id.action_icon); 46365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane setAlpha(icon, shouldAnimate, titleAlpha); 46465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 46565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane ImageView chevron = (ImageView) v.findViewById(R.id.action_next_chevron); 46665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane setAlpha(chevron, shouldAnimate, chevronAlpha); 46765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 46865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 46965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane private void setAlpha(View view, boolean shouldAnimate, float alpha) { 47065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane if (shouldAnimate) { 47165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane view.animate().alpha(alpha) 47265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane .setDuration(mAnimationDuration) 47365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane .setInterpolator(ALPHA_DECEL) 47465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane .start(); 47565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } else { 47665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane view.setAlpha(alpha); 47765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 47865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 47965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 48065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 48165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane private class ActionOnKeyPressAnimator implements View.OnKeyListener { 48265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 48365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane private static final int SELECT_ANIM_DURATION = 100; 48465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane private static final int SELECT_ANIM_DELAY = 0; 48565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane private static final float SELECT_ANIM_SELECTED_ALPHA = 0.2f; 48665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane private static final float SELECT_ANIM_UNSELECTED_ALPHA = 1.0f; 48765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane private static final float CHECKMARK_ANIM_UNSELECTED_ALPHA = 0.0f; 48865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane private static final float CHECKMARK_ANIM_SELECTED_ALPHA = 1.0f; 48965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 49065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane private boolean mKeyPressed = false; 49165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane private Listener mListener; 49265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 49365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane public ActionOnKeyPressAnimator(Listener listener) { 49465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane mListener = listener; 49565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 49665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 49765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane public void setListener(Listener listener) { 49865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane mListener = listener; 49965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 50065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 50165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane /** 50265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane * Now only handles KEYCODE_ENTER and KEYCODE_NUMPAD_ENTER key event. 50365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane */ 50465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane @Override 50565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane public boolean onKey(View v, int keyCode, KeyEvent event) { 50665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane if (v == null) { 50765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane return false; 50865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 50965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane boolean handled = false; 51065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane Layout.LayoutRow layoutRow = 51165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane ((LayoutRowViewHolder) v.getTag(R.id.action_title)).getLayoutRow(); 51265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane switch (keyCode) { 51365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane case KeyEvent.KEYCODE_DPAD_CENTER: 51465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane case KeyEvent.KEYCODE_NUMPAD_ENTER: 51565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane case KeyEvent.KEYCODE_BUTTON_X: 51665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane case KeyEvent.KEYCODE_BUTTON_Y: 51765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane case KeyEvent.KEYCODE_ENTER: 51865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 51965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane if (!layoutRow.isEnabled() || layoutRow.infoOnly()) { 52065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane if (v.isSoundEffectsEnabled() 52165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane && event.getAction() == KeyEvent.ACTION_DOWN) { 52265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane playSound(v.getContext(), AudioManager.FX_KEYPRESS_INVALID); 52365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 52465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane return true; 52565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 52665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 52765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane switch (event.getAction()) { 52865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane case KeyEvent.ACTION_DOWN: 52965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane if (!mKeyPressed) { 53065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane mKeyPressed = true; 53165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 53265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane if (v.isSoundEffectsEnabled()) { 53365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane playSound(v.getContext(), AudioManager.FX_KEY_CLICK); 53465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 53565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 53665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane if (DEBUG) { 53765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane Log.d(TAG, "Enter Key down"); 53865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 53965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 54065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane prepareAndAnimateView(v, SELECT_ANIM_UNSELECTED_ALPHA, 54165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane SELECT_ANIM_SELECTED_ALPHA, SELECT_ANIM_DURATION, 54265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane SELECT_ANIM_DELAY, null, mKeyPressed); 54365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane handled = true; 54465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 54565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane break; 54665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane case KeyEvent.ACTION_UP: 54765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane if (mKeyPressed) { 54865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane mKeyPressed = false; 54965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 55065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane if (DEBUG) { 55165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane Log.d(TAG, "Enter Key up"); 55265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 55365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 55465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane prepareAndAnimateView(v, SELECT_ANIM_SELECTED_ALPHA, 55565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane SELECT_ANIM_UNSELECTED_ALPHA, SELECT_ANIM_DURATION, 55665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane SELECT_ANIM_DELAY, null, mKeyPressed); 55765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane handled = true; 55865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 55965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane break; 56065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane default: 56165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane break; 56265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 56365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane break; 56465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane default: 56565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane break; 56665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 56765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane return handled; 56865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 56965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 57065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane private void playSound(Context context, int soundEffect) { 57165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane AudioManager manager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE); 57265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane manager.playSoundEffect(soundEffect); 57365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 57465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 57565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane private void prepareAndAnimateView(final View v, float initAlpha, float destAlpha, 57665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane int duration, 57765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane int delay, Interpolator interpolator, final boolean pressed) { 57865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane if (v != null && v.getWindowToken() != null) { 57965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane final Layout.LayoutRow layoutRow = 58065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane ((LayoutRowViewHolder) v.getTag(R.id.action_title)).getLayoutRow(); 58165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 58265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane if (!pressed) { 58365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane fadeCheckmarks(v, layoutRow, duration, delay, interpolator); 58465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 58565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 58665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane v.setAlpha(initAlpha); 58765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane v.setLayerType(View.LAYER_TYPE_HARDWARE, null); 58865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane v.buildLayer(); 58965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane v.animate().alpha(destAlpha).setDuration(duration).setStartDelay(delay); 59065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane if (interpolator != null) { 59165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane v.animate().setInterpolator(interpolator); 59265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 59365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane v.animate().setListener(new AnimatorListenerAdapter() { 59465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane @Override 59565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane public void onAnimationEnd(Animator animation) { 59665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane v.setLayerType(View.LAYER_TYPE_NONE, null); 59765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane if (!pressed) { 59865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane if (mListener != null) { 59965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane mListener.onRowClicked(layoutRow); 60065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 60165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 60265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 60365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane }); 60465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane v.animate().start(); 60565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 60665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 60765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 60865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane private void fadeCheckmarks(final View v, final Layout.LayoutRow action, int duration, 60965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane int delay, Interpolator interpolator) { 61065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane int actionCheckSetId = action.getCheckSetId(); 61165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane if (actionCheckSetId != Layout.LayoutRow.NO_CHECK_SET) { 61265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane ViewGroup parent = (ViewGroup) v.getTag(R.layout.lb_dialog_action_list_item); 61365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 61465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane // Find any actions that are checked and are in the same group as the selected 61565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane // action. Fade their checkmarks out. 61665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane for (int i = 0, size = mLayoutRows.size(); i < size; i++) { 61765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane Layout.LayoutRow a = mLayoutRows.get(i); 61865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane if (a != action && a.getCheckSetId() == actionCheckSetId && a.isChecked()) { 61965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane a.setChecked(false); 62065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane View viewToAnimateOut = parent.getChildAt(i); 62165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane if (viewToAnimateOut != null) { 62265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane final View checkView = viewToAnimateOut.findViewById( 62365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane R.id.action_checkmark); 62465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane checkView.animate().alpha(CHECKMARK_ANIM_UNSELECTED_ALPHA) 62565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane .setDuration(duration).setStartDelay(delay); 62665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane if (interpolator != null) { 62765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane checkView.animate().setInterpolator(interpolator); 62865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 62965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane checkView.animate().setListener(new AnimatorListenerAdapter() { 63065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane @Override 63165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane public void onAnimationEnd(Animator animation) { 63265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane checkView.setVisibility(View.INVISIBLE); 63365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 63465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane }); 63565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 63665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 63765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 63865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 63965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane // If we we'ren't already checked, fade our checkmark in. 64065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane if (!action.isChecked()) { 64165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane action.setChecked(true); 64265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane final View checkView = v.findViewById(R.id.action_checkmark); 64365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane checkView.setVisibility(View.VISIBLE); 64465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane checkView.setAlpha(CHECKMARK_ANIM_UNSELECTED_ALPHA); 64565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane checkView.animate().alpha(CHECKMARK_ANIM_SELECTED_ALPHA).setDuration(duration) 64665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane .setStartDelay(delay); 64765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane if (interpolator != null) { 64865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane checkView.animate().setInterpolator(interpolator); 64965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 65065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane checkView.animate().setListener(null); 65165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 65265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 65365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 65465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 65565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 65665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane private static float getFloat(Resources res, int floatResId) { 65765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane TypedValue tv = new TypedValue(); 65865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane res.getValue(floatResId, tv, true); 65965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane return tv.getFloat(); 66065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 66165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane} 662