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.res.Resources; 2465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Laneimport android.database.DataSetObserver; 2565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Laneimport android.graphics.drawable.Drawable; 2665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Laneimport android.media.AudioManager; 2765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Laneimport android.net.Uri; 2865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Laneimport android.os.Handler; 2965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Laneimport android.os.Looper; 3065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Laneimport android.support.v7.widget.RecyclerView; 3165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Laneimport android.support.v7.widget.RecyclerView.ViewHolder; 3265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Laneimport android.text.TextUtils; 3365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Laneimport android.util.Log; 3465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Laneimport android.util.TypedValue; 3565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Laneimport android.view.KeyEvent; 3665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Laneimport android.view.LayoutInflater; 3765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Laneimport android.view.View; 3865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Laneimport android.view.ViewGroup; 3965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Laneimport android.view.WindowManager; 4065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Laneimport android.view.animation.DecelerateInterpolator; 4165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Laneimport android.view.animation.Interpolator; 4265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Laneimport android.widget.AdapterView.OnItemSelectedListener; 4365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Laneimport android.widget.ImageView; 4465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Laneimport android.widget.TextView; 4565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 46944e793b0520642950bd72c636d51fd72dee6517Tony Mantlerimport com.android.tv.settings.R; 4765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 4865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Laneimport java.security.InvalidParameterException; 4965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Laneimport java.util.ArrayList; 5065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 5165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane/** 5265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane * Adapter class which creates actions. 5365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane */ 5465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Laneclass SettingsLayoutAdapter extends RecyclerView.Adapter { 5565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane private static final String TAG = "SettingsLayoutAdapter"; 5665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane private static final boolean DEBUG = false; 5765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane private static final DecelerateInterpolator ALPHA_DECEL = new DecelerateInterpolator(2F); 5865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane private final Handler mRefreshViewHandler = new Handler(Looper.getMainLooper()); 5965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 6065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane /** 6165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane * Object listening for adapter events. 6265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane */ 6365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane public interface Listener { 6465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 6565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane /** 6665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane * Called when the user clicks on an action. 6765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane */ 683a17f1a50a44e8392f496606b522dfe35a4e1c39Tony Mantler void onRowClicked(Layout.LayoutRow item); 6965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 7065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 7165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane public interface OnFocusListener { 7265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 7365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane /** 7465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane * Called when the user focuses on an action. 7565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane */ 763a17f1a50a44e8392f496606b522dfe35a4e1c39Tony Mantler void onActionFocused(Layout.LayoutRow item); 7765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 7865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 7965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane private final ActionOnKeyPressAnimator mActionOnKeyPressAnimator; 8065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane private final ActionOnFocusAnimator mActionOnFocusAnimator; 8165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane private LayoutInflater mInflater; 8265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane private ArrayList<Layout.LayoutRow> mLayoutRows; 8365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane private Listener mListener; 8465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane private boolean mNoAnimateMode = false; 8501a5b81394670c6c5c2011673ed48c4fee1cf77bbulic private boolean mFocusListenerEnabled = true; 8665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 8765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane private final View.OnClickListener mOnClickListener = new View.OnClickListener() { 8865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane @Override 8965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane public void onClick(View v) { 9065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane if (v != null && v.getWindowToken() != null && mListener != null) { 9165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane mListener.onRowClicked(((LayoutRowViewHolder) v.getTag(R.id.action_title)). 9265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane getLayoutRow()); 9365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 9465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 9565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane }; 9665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 9765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane public SettingsLayoutAdapter(Listener listener, OnFocusListener onFocusListener) { 9865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane super(); 9965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane mListener = listener; 10065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane mActionOnKeyPressAnimator = new ActionOnKeyPressAnimator(listener); 10165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane mActionOnFocusAnimator = new ActionOnFocusAnimator(onFocusListener); 10265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 10365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 10465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane public void setLayoutRows(ArrayList<Layout.LayoutRow> layoutRows) { 10565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane mLayoutRows = layoutRows; 10665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 10765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 10865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane public void setNoAnimateMode() { 10965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane mNoAnimateMode = true; 11065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 11165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 11201a5b81394670c6c5c2011673ed48c4fee1cf77bbulic public void setFocusListenerEnabled(boolean enabled) { 11301a5b81394670c6c5c2011673ed48c4fee1cf77bbulic mFocusListenerEnabled = enabled; 11401a5b81394670c6c5c2011673ed48c4fee1cf77bbulic } 11501a5b81394670c6c5c2011673ed48c4fee1cf77bbulic 11665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane @Override 11765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane public int getItemViewType(int position) { 11865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane return mLayoutRows.get(position).getViewType(); 11965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 12065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 12165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane @Override 12265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { 12365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane if (mInflater == null) { 12465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane mInflater = (LayoutInflater) parent.getContext().getSystemService( 12565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane Context.LAYOUT_INFLATER_SERVICE); 12665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 1273a17f1a50a44e8392f496606b522dfe35a4e1c39Tony Mantler final View v; 12865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane switch (viewType) { 12965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane case Layout.LayoutRow.VIEW_TYPE_ACTION: 13065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane v = mInflater.inflate(R.layout.lb_dialog_action_list_item, parent, false); 13165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane break; 13265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane case Layout.LayoutRow.VIEW_TYPE_STATIC: 13365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane v = mInflater.inflate(R.layout.lb_dialog_static_list_item, parent, false); 13465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane break; 1353a17f1a50a44e8392f496606b522dfe35a4e1c39Tony Mantler case Layout.LayoutRow.VIEW_TYPE_WALLOFTEXT: 1363a17f1a50a44e8392f496606b522dfe35a4e1c39Tony Mantler v = mInflater.inflate(R.layout.lb_dialog_walloftext_list_item, parent, false); 1373a17f1a50a44e8392f496606b522dfe35a4e1c39Tony Mantler break; 1383a17f1a50a44e8392f496606b522dfe35a4e1c39Tony Mantler default: 1393a17f1a50a44e8392f496606b522dfe35a4e1c39Tony Mantler throw new IllegalStateException("View type not found: " + viewType); 14065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 14165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane v.setTag(R.layout.lb_dialog_action_list_item, parent); 14265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane LayoutRowViewHolder viewHolder = new LayoutRowViewHolder(v, mActionOnKeyPressAnimator, 14365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane mActionOnFocusAnimator, mOnClickListener); 14465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane viewHolder.init(viewType); 14565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane return viewHolder; 14665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 14765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 14865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane @Override 14965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane public void onBindViewHolder(RecyclerView.ViewHolder baseHolder, int position) { 15065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane LayoutRowViewHolder holder = (LayoutRowViewHolder) baseHolder; 15165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane if (position < mLayoutRows.size()) { 15267d5f4a4b27ea7078ed59486ea681c7e78d90e74Tony Mantler holder.bind(mLayoutRows.get(position), position); 15365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 15465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 15565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 15665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane @Override 15765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane public int getItemCount() { 15865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane return mLayoutRows.size(); 15965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 16065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 16165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane public void setListener(Listener listener) { 16265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane mListener = listener; 16365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane mActionOnKeyPressAnimator.setListener(listener); 16465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 16565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 16665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane public void setOnFocusListener(OnFocusListener onFocusListener) { 16765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane mActionOnFocusAnimator.setOnFocusListener(onFocusListener); 16865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 16965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 17065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane public void registerDataSetObserver(DataSetObserver dataSetObserver) { 17165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 17265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 17365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane public void setOnItemSelectedListener(OnItemSelectedListener listener) { 17465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 17565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 17665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane private class LayoutRowViewHolder extends ViewHolder implements 17765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane Layout.ContentNodeRefreshListener { 17865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 17965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane private class RefreshDescription implements Runnable { 18065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane public String mDescriptionText; 18165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 18265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane @Override 18365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane public void run() { 18465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane mDescription.setText(mDescriptionText); 18565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 18665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 18765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 18865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane private final ActionOnKeyPressAnimator mActionOnKeyPressAnimator; 18965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane private final ActionOnFocusAnimator mActionOnFocusAnimator; 19065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane private final View.OnClickListener mViewOnClickListener; 19165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane private Layout.LayoutRow mLayoutRow; 19265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane private TextView mDescription = null; 19365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane private TextView mTitle; 19465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane private ImageView mCheckmarkView; 19565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane private ImageView mIndicatorView; 19665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane private View mContent; 19765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane private ImageView mChevronView; 19867d5f4a4b27ea7078ed59486ea681c7e78d90e74Tony Mantler private View mHairlineView; 19965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane private int mViewType; 20065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane private RefreshDescription mRefreshDescription; 20165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 20265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane public LayoutRowViewHolder(View v, ActionOnKeyPressAnimator actionOnKeyPressAnimator, 20365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane ActionOnFocusAnimator actionOnFocusAnimator, 20465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane View.OnClickListener viewOnClickListener) { 20565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane super(v); 20665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane mActionOnKeyPressAnimator = actionOnKeyPressAnimator; 20765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane mActionOnFocusAnimator = actionOnFocusAnimator; 20865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane mViewOnClickListener = viewOnClickListener; 20965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 21065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 21165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane public Layout.LayoutRow getLayoutRow() { 21265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane return mLayoutRow; 21365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 21465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 21565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane public void init(int viewType) { 21665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane mViewType = viewType; 21765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane mTitle = (TextView) itemView.findViewById(R.id.action_title); 21865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane if (mViewType == Layout.LayoutRow.VIEW_TYPE_ACTION) { 21965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane mDescription = (TextView) itemView.findViewById(R.id.action_description); 22065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 22165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane mCheckmarkView = (ImageView) itemView.findViewById(R.id.action_checkmark); 22265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane mIndicatorView = (ImageView) itemView.findViewById(R.id.action_icon); 22365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane mContent = itemView.findViewById(R.id.action_content); 22465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane mChevronView = (ImageView) itemView.findViewById(R.id.action_next_chevron); 22567d5f4a4b27ea7078ed59486ea681c7e78d90e74Tony Mantler mHairlineView = itemView.findViewById(R.id.static_hairline); 22665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane itemView.setTag(R.id.action_title, this); 22765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane itemView.setOnKeyListener(mActionOnKeyPressAnimator); 22865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane itemView.setOnClickListener(mViewOnClickListener); 22965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane itemView.setOnFocusChangeListener(mActionOnFocusAnimator); 23065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 23165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 23265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane //TODO need to create separate xxxViewHolder classes to eliminate tests of "mViewType". 23365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane public void onRefreshView() { 23465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane if (mViewType == Layout.LayoutRow.VIEW_TYPE_ACTION) { 23565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane Layout.StringGetter description = mLayoutRow.getDescription(); 23665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane if (description != null) { 23765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane String text = description.get(); 23865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane if (!TextUtils.equals(mRefreshDescription.mDescriptionText, text)) { 23965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane mRefreshDescription.mDescriptionText = text; 24065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane mRefreshViewHandler.removeCallbacks(mRefreshDescription); 24165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane mRefreshViewHandler.post(mRefreshDescription); 24265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 24365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 24465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 24565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 24665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 24767d5f4a4b27ea7078ed59486ea681c7e78d90e74Tony Mantler public void bind(Layout.LayoutRow layoutRow, int position) { 24865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane mLayoutRow = layoutRow; 24965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane if (mViewType != layoutRow.getViewType()) { 25065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane throw new InvalidParameterException("view type does not match"); 25165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 25265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 25365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane if (mViewType == Layout.LayoutRow.VIEW_TYPE_ACTION) { 25465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane Layout.StringGetter description = layoutRow.getDescription(); 25565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane if (description != null) { 25665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane mRefreshDescription = new RefreshDescription(); 25765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane String text = description.get(); 25865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane mDescription.setText(text); 25965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane mRefreshDescription.mDescriptionText = text; 26065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane mDescription.setVisibility(View.VISIBLE); 26165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane description.setListener(this); 26265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } else { 26365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane mDescription.setVisibility(View.GONE); 26465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 26567d5f4a4b27ea7078ed59486ea681c7e78d90e74Tony Mantler } else if (mViewType == Layout.LayoutRow.VIEW_TYPE_STATIC && mHairlineView != null) { 26667d5f4a4b27ea7078ed59486ea681c7e78d90e74Tony Mantler mHairlineView.setVisibility(position == 0 ? View.GONE : View.VISIBLE); 26765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 26865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 26965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane mTitle.setText(layoutRow.getTitle()); 27067d5f4a4b27ea7078ed59486ea681c7e78d90e74Tony Mantler if (mCheckmarkView != null) { 27167d5f4a4b27ea7078ed59486ea681c7e78d90e74Tony Mantler mCheckmarkView.setVisibility(layoutRow.isChecked() ? View.VISIBLE : View.INVISIBLE); 27267d5f4a4b27ea7078ed59486ea681c7e78d90e74Tony Mantler } 273b1bd2fe28d123e889d02f5830f0772d2d255ad60Tony Mantler layoutRow.getChecked().setListener(this); 27465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 27567d5f4a4b27ea7078ed59486ea681c7e78d90e74Tony Mantler if (mContent != null) { 27667d5f4a4b27ea7078ed59486ea681c7e78d90e74Tony Mantler ViewGroup.LayoutParams contentLp = mContent.getLayoutParams(); 27767d5f4a4b27ea7078ed59486ea681c7e78d90e74Tony Mantler if (mIndicatorView != null && setIndicator(mIndicatorView, layoutRow)) { 27867d5f4a4b27ea7078ed59486ea681c7e78d90e74Tony Mantler contentLp.width = itemView.getContext().getResources() 27967d5f4a4b27ea7078ed59486ea681c7e78d90e74Tony Mantler .getDimensionPixelSize(R.dimen.lb_action_text_width); 28067d5f4a4b27ea7078ed59486ea681c7e78d90e74Tony Mantler } else { 28167d5f4a4b27ea7078ed59486ea681c7e78d90e74Tony Mantler contentLp.width = itemView.getContext().getResources() 28267d5f4a4b27ea7078ed59486ea681c7e78d90e74Tony Mantler .getDimensionPixelSize(R.dimen.lb_action_text_width_no_icon); 28367d5f4a4b27ea7078ed59486ea681c7e78d90e74Tony Mantler } 28467d5f4a4b27ea7078ed59486ea681c7e78d90e74Tony Mantler mContent.setLayoutParams(contentLp); 28565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 28665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 28767d5f4a4b27ea7078ed59486ea681c7e78d90e74Tony Mantler if (mChevronView != null) { 28867d5f4a4b27ea7078ed59486ea681c7e78d90e74Tony Mantler mChevronView.setVisibility(layoutRow.hasNext() ? View.VISIBLE : View.INVISIBLE); 28967d5f4a4b27ea7078ed59486ea681c7e78d90e74Tony Mantler } 29065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 29165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane mActionOnFocusAnimator.unFocus(itemView); 29265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 29365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 29465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane private boolean setIndicator(final ImageView indicatorView, Layout.LayoutRow action) { 29565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane Drawable indicator = action.getIcon(); 29665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane if (indicator != null) { 29765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane indicatorView.setImageDrawable(indicator); 29865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane indicatorView.setVisibility(View.VISIBLE); 29965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } else { 30065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane Uri iconUri = action.getIconUri(); 30165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane if (iconUri != null) { 30265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane indicatorView.setVisibility(View.INVISIBLE); 30365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } else { 30465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane indicatorView.setVisibility(View.GONE); 30565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane return false; 30665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 30765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 30865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane return true; 30965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 31065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 31165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane private void fadeIn(View v) { 31265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane ObjectAnimator alphaAnimator = ObjectAnimator.ofFloat(v, "alpha", 0f, 1f); 31365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane alphaAnimator.setDuration( 31465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane v.getContext().getResources().getInteger( 31565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane android.R.integer.config_mediumAnimTime)); 31665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane alphaAnimator.start(); 31765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 31865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 31965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane /** 32065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane * @return the max height in pixels the description can be such that the 32165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane * action nicely takes up the entire screen. 32265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane */ 32365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane private int getDescriptionMaxHeight(Context context, TextView title) { 32465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane final Resources res = context.getResources(); 32565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane final float verticalPadding = 32665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane res.getDimension(R.dimen.lb_dialog_list_item_vertical_padding); 32765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane final int titleMaxLines = res.getInteger(R.integer.lb_dialog_action_title_max_lines); 32865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane final int displayHeight = ((WindowManager) context.getSystemService( 32965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane Context.WINDOW_SERVICE)).getDefaultDisplay().getHeight(); 33065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 33165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane // The 2 multiplier on the title height calculation is a 33265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane // conservative estimate for font padding which can not be 33365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane // calculated at this stage since the view hasn't been rendered yet. 33465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane return (int) (displayHeight - 33565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 2 * verticalPadding - 2 * titleMaxLines * title.getLineHeight()); 33665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 33765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 33865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 33965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 34065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane private class ActionOnFocusAnimator implements View.OnFocusChangeListener { 34165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 34265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane private boolean mResourcesSet; 34365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane private float mUnselectedAlpha; 34465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane private float mSelectedTitleAlpha; 34565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane private float mDisabledTitleAlpha; 34665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane private float mSelectedDescriptionAlpha; 34765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane private float mDisabledDescriptionAlpha; 34865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane private float mUnselectedDescriptionAlpha; 34965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane private float mSelectedChevronAlpha; 35065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane private float mDisabledChevronAlpha; 35165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane private int mAnimationDuration; 35265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane private OnFocusListener mOnFocusListener; 35365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane private View mSelectedView; 35465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 35565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane ActionOnFocusAnimator(OnFocusListener onFocusListener) { 35665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane mOnFocusListener = onFocusListener; 35765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 35865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 35965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane public void setOnFocusListener(OnFocusListener onFocusListener) { 36065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane mOnFocusListener = onFocusListener; 36165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 36265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 36365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane public void unFocus(View v) { 36465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane changeFocus((v != null) ? v : mSelectedView, false, false); 36565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 36665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 36765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane @Override 36865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane public void onFocusChange(View v, boolean hasFocus) { 36965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane if (hasFocus) { 37065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane mSelectedView = v; 37165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane if (mNoAnimateMode) { 37265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane mNoAnimateMode = false; 37365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane changeFocus(v, true /* hasFocus */, false /* shouldAnimate */); 37465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } else { 37565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane changeFocus(v, true /* hasFocus */, true /* shouldAnimate */); 37601a5b81394670c6c5c2011673ed48c4fee1cf77bbulic if (mOnFocusListener != null && mFocusListenerEnabled) { 37765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane // We still call onActionFocused so that listeners can clear state if they 37865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane // want. 37965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane mOnFocusListener.onActionFocused( 38065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane ((LayoutRowViewHolder) v.getTag(R.id.action_title)).getLayoutRow()); 38165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 38265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 38365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } else { 38465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane if (mSelectedView == v) { 38565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane mSelectedView = null; 38665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 38765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane changeFocus(v, false /* hasFocus */, true /* shouldAnimate */); 38865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 38965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 39065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 39165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane private void changeFocus(View v, boolean hasFocus, boolean shouldAnimate) { 39265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane if (v == null) { 39365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane return; 39465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 39565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 39665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane if (!mResourcesSet) { 39765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane mResourcesSet = true; 39865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane final Resources res = v.getContext().getResources(); 39965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 40065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane mAnimationDuration = res.getInteger(R.integer.lb_dialog_animation_duration); 40165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 40265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane mUnselectedAlpha = 40365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane getFloat(res, R.string.lb_dialog_list_item_unselected_text_alpha); 40465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 40565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane mSelectedTitleAlpha = 40665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane getFloat(res, R.string.lb_dialog_list_item_selected_title_text_alpha); 40765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane mDisabledTitleAlpha = 40865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane getFloat(res, R.string.lb_dialog_list_item_disabled_title_text_alpha); 40965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 41065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane mSelectedDescriptionAlpha = 41165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane getFloat(res, R.string.lb_dialog_list_item_selected_description_text_alpha); 41265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane mUnselectedDescriptionAlpha = getFloat(res, 41365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane R.string.lb_dialog_list_item_unselected_description_text_alpha); 41465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane mDisabledDescriptionAlpha = 41565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane getFloat(res, R.string.lb_dialog_list_item_disabled_description_text_alpha); 41665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 41765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane mSelectedChevronAlpha = getFloat(res, 41865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane R.string.lb_dialog_list_item_selected_chevron_background_alpha); 41965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane mDisabledChevronAlpha = getFloat(res, 42065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane R.string.lb_dialog_list_item_disabled_chevron_background_alpha); 42165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 42265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 42365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane Layout.LayoutRow layoutRow = 42465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane ((LayoutRowViewHolder) v.getTag(R.id.action_title)).getLayoutRow(); 42565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 42665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane float titleAlpha; 42765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane if (layoutRow.isEnabled() && !layoutRow.infoOnly()) { 42865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane titleAlpha = hasFocus ? mSelectedTitleAlpha : mUnselectedAlpha; 42965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } else { 43065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane titleAlpha = mDisabledTitleAlpha; 43165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 43265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane float descriptionAlpha; 43365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane if (!hasFocus || layoutRow.infoOnly()) { 43465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane descriptionAlpha = mUnselectedDescriptionAlpha; 43565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } else { 43665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane descriptionAlpha = layoutRow.isEnabled() ? mSelectedDescriptionAlpha : 43765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane mDisabledDescriptionAlpha; 43865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 43965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane float chevronAlpha; 44065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane if (layoutRow.hasNext() && !layoutRow.infoOnly()) { 44165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane chevronAlpha = 44265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane layoutRow.isEnabled() ? mSelectedChevronAlpha : mDisabledChevronAlpha; 44365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } else { 44465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane chevronAlpha = 0; 44565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 44665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 44767d5f4a4b27ea7078ed59486ea681c7e78d90e74Tony Mantler final View title = v.findViewById(R.id.action_title); 44867d5f4a4b27ea7078ed59486ea681c7e78d90e74Tony Mantler if (title != null) { 44967d5f4a4b27ea7078ed59486ea681c7e78d90e74Tony Mantler setAlpha(title, shouldAnimate, titleAlpha); 45067d5f4a4b27ea7078ed59486ea681c7e78d90e74Tony Mantler } 45165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 45267d5f4a4b27ea7078ed59486ea681c7e78d90e74Tony Mantler final View description = v.findViewById(R.id.action_description); 45365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane if (description != null) { 45465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane setAlpha(description, shouldAnimate, descriptionAlpha); 45565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 45665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 45767d5f4a4b27ea7078ed59486ea681c7e78d90e74Tony Mantler final View checkmark = v.findViewById(R.id.action_checkmark); 45867d5f4a4b27ea7078ed59486ea681c7e78d90e74Tony Mantler if (checkmark != null) { 45967d5f4a4b27ea7078ed59486ea681c7e78d90e74Tony Mantler setAlpha(checkmark, shouldAnimate, titleAlpha); 46067d5f4a4b27ea7078ed59486ea681c7e78d90e74Tony Mantler } 46165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 46267d5f4a4b27ea7078ed59486ea681c7e78d90e74Tony Mantler final View icon = v.findViewById(R.id.action_icon); 46367d5f4a4b27ea7078ed59486ea681c7e78d90e74Tony Mantler if (icon != null) { 46467d5f4a4b27ea7078ed59486ea681c7e78d90e74Tony Mantler setAlpha(icon, shouldAnimate, titleAlpha); 46567d5f4a4b27ea7078ed59486ea681c7e78d90e74Tony Mantler } 46665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 46767d5f4a4b27ea7078ed59486ea681c7e78d90e74Tony Mantler final View chevron = v.findViewById(R.id.action_next_chevron); 46867d5f4a4b27ea7078ed59486ea681c7e78d90e74Tony Mantler if (chevron != null) { 46967d5f4a4b27ea7078ed59486ea681c7e78d90e74Tony Mantler setAlpha(chevron, shouldAnimate, chevronAlpha); 47067d5f4a4b27ea7078ed59486ea681c7e78d90e74Tony Mantler } 47165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 47265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 47365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane private void setAlpha(View view, boolean shouldAnimate, float alpha) { 47465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane if (shouldAnimate) { 47565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane view.animate().alpha(alpha) 47665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane .setDuration(mAnimationDuration) 47765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane .setInterpolator(ALPHA_DECEL) 47865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane .start(); 47965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } else { 48065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane view.setAlpha(alpha); 48165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 48265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 48365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 48465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 48565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane private class ActionOnKeyPressAnimator implements View.OnKeyListener { 48665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 48765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane private static final int SELECT_ANIM_DURATION = 100; 48865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane private static final int SELECT_ANIM_DELAY = 0; 48965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane private static final float SELECT_ANIM_SELECTED_ALPHA = 0.2f; 49065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane private static final float SELECT_ANIM_UNSELECTED_ALPHA = 1.0f; 49165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane private static final float CHECKMARK_ANIM_UNSELECTED_ALPHA = 0.0f; 49265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane private static final float CHECKMARK_ANIM_SELECTED_ALPHA = 1.0f; 49365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 49465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane private boolean mKeyPressed = false; 49565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane private Listener mListener; 49665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 49765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane public ActionOnKeyPressAnimator(Listener listener) { 49865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane mListener = listener; 49965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 50065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 50165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane public void setListener(Listener listener) { 50265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane mListener = listener; 50365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 50465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 50565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane /** 50665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane * Now only handles KEYCODE_ENTER and KEYCODE_NUMPAD_ENTER key event. 50765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane */ 50865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane @Override 50965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane public boolean onKey(View v, int keyCode, KeyEvent event) { 51065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane if (v == null) { 51165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane return false; 51265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 51365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane boolean handled = false; 51465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane Layout.LayoutRow layoutRow = 51565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane ((LayoutRowViewHolder) v.getTag(R.id.action_title)).getLayoutRow(); 51665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane switch (keyCode) { 51765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane case KeyEvent.KEYCODE_DPAD_CENTER: 51865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane case KeyEvent.KEYCODE_NUMPAD_ENTER: 51965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane case KeyEvent.KEYCODE_BUTTON_X: 52065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane case KeyEvent.KEYCODE_BUTTON_Y: 52165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane case KeyEvent.KEYCODE_ENTER: 52265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 52365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane if (!layoutRow.isEnabled() || layoutRow.infoOnly()) { 52465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane if (v.isSoundEffectsEnabled() 52565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane && event.getAction() == KeyEvent.ACTION_DOWN) { 52665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane playSound(v.getContext(), AudioManager.FX_KEYPRESS_INVALID); 52765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 52865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane return true; 52965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 53065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 53165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane switch (event.getAction()) { 53265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane case KeyEvent.ACTION_DOWN: 53365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane if (!mKeyPressed) { 53465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane mKeyPressed = true; 53565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 53665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane if (v.isSoundEffectsEnabled()) { 53765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane playSound(v.getContext(), AudioManager.FX_KEY_CLICK); 53865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 53965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 54065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane if (DEBUG) { 54165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane Log.d(TAG, "Enter Key down"); 54265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 54365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 54465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane prepareAndAnimateView(v, SELECT_ANIM_UNSELECTED_ALPHA, 54565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane SELECT_ANIM_SELECTED_ALPHA, SELECT_ANIM_DURATION, 54665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane SELECT_ANIM_DELAY, null, mKeyPressed); 54765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane handled = true; 54865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 54965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane break; 55065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane case KeyEvent.ACTION_UP: 55165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane if (mKeyPressed) { 55265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane mKeyPressed = false; 55365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 55465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane if (DEBUG) { 55565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane Log.d(TAG, "Enter Key up"); 55665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 55765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 55865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane prepareAndAnimateView(v, SELECT_ANIM_SELECTED_ALPHA, 55965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane SELECT_ANIM_UNSELECTED_ALPHA, SELECT_ANIM_DURATION, 56065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane SELECT_ANIM_DELAY, null, mKeyPressed); 56165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane handled = true; 56265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 56365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane break; 56465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane default: 56565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane break; 56665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 56765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane break; 56865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane default: 56965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane break; 57065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 57165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane return handled; 57265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 57365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 57465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane private void playSound(Context context, int soundEffect) { 57565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane AudioManager manager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE); 57665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane manager.playSoundEffect(soundEffect); 57765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 57865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 57965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane private void prepareAndAnimateView(final View v, float initAlpha, float destAlpha, 58065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane int duration, 58165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane int delay, Interpolator interpolator, final boolean pressed) { 58265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane if (v != null && v.getWindowToken() != null) { 58365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane final Layout.LayoutRow layoutRow = 58465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane ((LayoutRowViewHolder) v.getTag(R.id.action_title)).getLayoutRow(); 58565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 58665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane if (!pressed) { 58765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane fadeCheckmarks(v, layoutRow, duration, delay, interpolator); 58865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 58965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 59065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane v.setAlpha(initAlpha); 59165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane v.setLayerType(View.LAYER_TYPE_HARDWARE, null); 59265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane v.buildLayer(); 59365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane v.animate().alpha(destAlpha).setDuration(duration).setStartDelay(delay); 59465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane if (interpolator != null) { 59565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane v.animate().setInterpolator(interpolator); 59665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 59765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane v.animate().setListener(new AnimatorListenerAdapter() { 59865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane @Override 59965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane public void onAnimationEnd(Animator animation) { 60065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane v.setLayerType(View.LAYER_TYPE_NONE, null); 60165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane if (!pressed) { 60265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane if (mListener != null) { 60365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane mListener.onRowClicked(layoutRow); 60465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 60565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 60665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 60765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane }); 60865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane v.animate().start(); 60965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 61065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 61165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 61265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane private void fadeCheckmarks(final View v, final Layout.LayoutRow action, int duration, 61365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane int delay, Interpolator interpolator) { 61465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane int actionCheckSetId = action.getCheckSetId(); 61565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane if (actionCheckSetId != Layout.LayoutRow.NO_CHECK_SET) { 61665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane ViewGroup parent = (ViewGroup) v.getTag(R.layout.lb_dialog_action_list_item); 61765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 61865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane // Find any actions that are checked and are in the same group as the selected 61965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane // action. Fade their checkmarks out. 62065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane for (int i = 0, size = mLayoutRows.size(); i < size; i++) { 62165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane Layout.LayoutRow a = mLayoutRows.get(i); 62265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane if (a != action && a.getCheckSetId() == actionCheckSetId && a.isChecked()) { 62365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane a.setChecked(false); 62465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane View viewToAnimateOut = parent.getChildAt(i); 62565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane if (viewToAnimateOut != null) { 62665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane final View checkView = viewToAnimateOut.findViewById( 62765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane R.id.action_checkmark); 62867d5f4a4b27ea7078ed59486ea681c7e78d90e74Tony Mantler if (checkView != null) { 62967d5f4a4b27ea7078ed59486ea681c7e78d90e74Tony Mantler checkView.animate().alpha(CHECKMARK_ANIM_UNSELECTED_ALPHA) 63067d5f4a4b27ea7078ed59486ea681c7e78d90e74Tony Mantler .setDuration(duration).setStartDelay(delay); 63167d5f4a4b27ea7078ed59486ea681c7e78d90e74Tony Mantler if (interpolator != null) { 63267d5f4a4b27ea7078ed59486ea681c7e78d90e74Tony Mantler checkView.animate().setInterpolator(interpolator); 63365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 63467d5f4a4b27ea7078ed59486ea681c7e78d90e74Tony Mantler checkView.animate().setListener(new AnimatorListenerAdapter() { 63567d5f4a4b27ea7078ed59486ea681c7e78d90e74Tony Mantler @Override 63667d5f4a4b27ea7078ed59486ea681c7e78d90e74Tony Mantler public void onAnimationEnd(Animator animation) { 63767d5f4a4b27ea7078ed59486ea681c7e78d90e74Tony Mantler checkView.setVisibility(View.INVISIBLE); 63867d5f4a4b27ea7078ed59486ea681c7e78d90e74Tony Mantler } 63967d5f4a4b27ea7078ed59486ea681c7e78d90e74Tony Mantler }); 64067d5f4a4b27ea7078ed59486ea681c7e78d90e74Tony Mantler } 64165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 64265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 64365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 64465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 64565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane // If we we'ren't already checked, fade our checkmark in. 64665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane if (!action.isChecked()) { 64765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane action.setChecked(true); 64865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane final View checkView = v.findViewById(R.id.action_checkmark); 64967d5f4a4b27ea7078ed59486ea681c7e78d90e74Tony Mantler if (checkView != null) { 65067d5f4a4b27ea7078ed59486ea681c7e78d90e74Tony Mantler checkView.setVisibility(View.VISIBLE); 65167d5f4a4b27ea7078ed59486ea681c7e78d90e74Tony Mantler checkView.setAlpha(CHECKMARK_ANIM_UNSELECTED_ALPHA); 65267d5f4a4b27ea7078ed59486ea681c7e78d90e74Tony Mantler checkView.animate().alpha(CHECKMARK_ANIM_SELECTED_ALPHA) 65367d5f4a4b27ea7078ed59486ea681c7e78d90e74Tony Mantler .setDuration(duration) 65467d5f4a4b27ea7078ed59486ea681c7e78d90e74Tony Mantler .setStartDelay(delay); 65567d5f4a4b27ea7078ed59486ea681c7e78d90e74Tony Mantler if (interpolator != null) { 65667d5f4a4b27ea7078ed59486ea681c7e78d90e74Tony Mantler checkView.animate().setInterpolator(interpolator); 65767d5f4a4b27ea7078ed59486ea681c7e78d90e74Tony Mantler } 65867d5f4a4b27ea7078ed59486ea681c7e78d90e74Tony Mantler checkView.animate().setListener(null); 65965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 66065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 66165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 66265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 66365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 66465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 66565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane private static float getFloat(Resources res, int floatResId) { 66665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane TypedValue tv = new TypedValue(); 66765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane res.getValue(floatResId, tv, true); 66865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane return tv.getFloat(); 66965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 67065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane} 671