171d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu/* 271d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu * Copyright (C) 2015 The Android Open Source Project 371d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu * 471d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except 571d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu * in compliance with the License. You may obtain a copy of the License at 671d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu * 771d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu * http://www.apache.org/licenses/LICENSE-2.0 871d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu * 971d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu * Unless required by applicable law or agreed to in writing, software distributed under the License 1071d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 1171d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu * or implied. See the License for the specific language governing permissions and limitations under 1271d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu * the License. 1371d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu */ 1471d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu 1571d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gupackage android.support.v17.leanback.widget.picker; 1671d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu 1771d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Guimport android.content.Context; 180f96ae4965103bade4bebe7776b2ee35cd603112Dake Guimport android.graphics.Rect; 1971d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Guimport android.support.v17.leanback.R; 2071d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Guimport android.support.v17.leanback.widget.OnChildViewHolderSelectedListener; 2171d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Guimport android.support.v17.leanback.widget.VerticalGridView; 2271d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Guimport android.support.v7.widget.RecyclerView; 2371d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Guimport android.util.AttributeSet; 2471d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Guimport android.util.TypedValue; 252e42db84057616ff5fc755ab55debef731015d3aDake Guimport android.view.KeyEvent; 2671d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Guimport android.view.LayoutInflater; 2771d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Guimport android.view.View; 2871d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Guimport android.view.ViewGroup; 2971d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Guimport android.view.animation.AccelerateInterpolator; 3071d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Guimport android.view.animation.DecelerateInterpolator; 3171d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Guimport android.view.animation.Interpolator; 3271d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Guimport android.widget.FrameLayout; 3371d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Guimport android.widget.TextView; 3471d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu 3571d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Guimport java.util.ArrayList; 3671d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Guimport java.util.List; 3771d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu 3871d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu/** 39b19799d69cbbe7f7ca104520e9b07312ab7539afDake Gu * Picker is a widget showing multiple customized {@link PickerColumn}s. The PickerColumns are 40b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu * initialized in {@link #setColumns(List)}. Call {@link #setColumnAt(int, PickerColumn)} if the 41b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu * column value range or labels change. Call {@link #setColumnValue(int, int, boolean)} to update 42b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu * the current value of PickerColumn. 432e42db84057616ff5fc755ab55debef731015d3aDake Gu * <p> 442e42db84057616ff5fc755ab55debef731015d3aDake Gu * Picker has two states and will change height: 45b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu * <li>{@link #isActivated()} is true: Picker shows typically three items vertically (see 46b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu * {@link #getActivatedVisibleItemCount()}}. Columns other than {@link #getSelectedColumn()} still 47b19799d69cbbe7f7ca104520e9b07312ab7539afDake Gu * shows one item if the Picker is focused. On a touch screen device, the Picker will not get focus 48b19799d69cbbe7f7ca104520e9b07312ab7539afDake Gu * so it always show three items on all columns. On a non-touch device (a TV), the Picker will show 49b19799d69cbbe7f7ca104520e9b07312ab7539afDake Gu * three items only on currently activated column. If the Picker has focus, it will intercept DPAD 50b19799d69cbbe7f7ca104520e9b07312ab7539afDake Gu * directions and select activated column. 51b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu * <li>{@link #isActivated()} is false: Picker shows one item vertically (see 52b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu * {@link #getVisibleItemCount()}) on all columns. The size of Picker shrinks. 5371d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu */ 5471d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gupublic class Picker extends FrameLayout { 5571d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu 5671d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu public interface PickerValueListener { 5771d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu public void onValueChanged(Picker picker, int column); 5871d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu } 5971d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu 6071d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu private ViewGroup mRootView; 612e42db84057616ff5fc755ab55debef731015d3aDake Gu private ViewGroup mPickerView; 620f96ae4965103bade4bebe7776b2ee35cd603112Dake Gu private final List<VerticalGridView> mColumnViews = new ArrayList<VerticalGridView>(); 6371d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu private ArrayList<PickerColumn> mColumns; 6471d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu 6571d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu private float mUnfocusedAlpha; 6671d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu private float mFocusedAlpha; 6771d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu private float mVisibleColumnAlpha; 6871d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu private float mInvisibleColumnAlpha; 6971d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu private int mAlphaAnimDuration; 7071d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu private Interpolator mDecelerateInterpolator; 7171d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu private Interpolator mAccelerateInterpolator; 7271d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu private ArrayList<PickerValueListener> mListeners; 73b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu private float mVisibleItemsActivated = 3; 742e42db84057616ff5fc755ab55debef731015d3aDake Gu private float mVisibleItems = 1; 75b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu private int mSelectedColumn = 0; 7671d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu 77b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu private CharSequence mSeparator; 78b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu private int mPickerItemLayoutId = R.layout.lb_picker_item; 79b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu private int mPickerItemTextViewId = 0; 8071d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu 8171d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu /** 82b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu * Gets separator string between columns. 8371d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu */ 84b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu public final CharSequence getSeparator() { 85b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu return mSeparator; 8671d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu } 8771d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu 8871d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu /** 89b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu * Sets separator String between Picker columns. 90b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu * @param seperator Separator String between Picker columns. 9171d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu */ 92b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu public final void setSeparator(CharSequence seperator) { 93b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu mSeparator = seperator; 9471d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu } 9571d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu 9671d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu /** 9771d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu * Classes extending {@link Picker} can choose to override this method to 98b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu * supply the {@link Picker}'s item's layout id 9971d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu */ 100b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu public final int getPickerItemLayoutId() { 101b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu return mPickerItemLayoutId; 10271d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu } 10371d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu 10471d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu /** 105b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu * Returns the {@link Picker}'s item's {@link TextView}'s id from within the 106b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu * layout provided by {@link Picker#getPickerItemLayoutId()} or 0 if the 107b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu * layout provided by {@link Picker#getPickerItemLayoutId()} is a {link 108b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu * TextView}. 10971d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu */ 110b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu public final int getPickerItemTextViewId() { 111b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu return mPickerItemTextViewId; 11271d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu } 11371d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu 11471d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu /** 115b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu * Sets the {@link Picker}'s item's {@link TextView}'s id from within the 11671d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu * layout provided by {@link Picker#getPickerItemLayoutId()} or 0 if the 11771d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu * layout provided by {@link Picker#getPickerItemLayoutId()} is a {link 11871d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu * TextView}. 119b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu * @param textViewId View id of TextView inside a Picker item, or 0 if the Picker item is a 120b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu * TextView. 12171d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu */ 122b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu public final void setPickerItemTextViewId(int textViewId) { 123b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu mPickerItemTextViewId = textViewId; 12471d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu } 12571d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu 12671d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu /** 12771d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu * Creates a Picker widget. 12871d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu * @param context 12971d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu * @param attrs 13071d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu * @param defStyleAttr 13171d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu */ 13271d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu public Picker(Context context, AttributeSet attrs, int defStyleAttr) { 13371d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu super(context, attrs, defStyleAttr); 1342e42db84057616ff5fc755ab55debef731015d3aDake Gu // Make it enabled and clickable to receive Click event. 1352e42db84057616ff5fc755ab55debef731015d3aDake Gu setEnabled(true); 13671d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu 13771d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu mFocusedAlpha = 1f; //getFloat(R.dimen.list_item_selected_title_text_alpha); 13871d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu mUnfocusedAlpha = 1f; //getFloat(R.dimen.list_item_unselected_text_alpha); 13971d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu mVisibleColumnAlpha = 0.5f; //getFloat(R.dimen.picker_item_visible_column_item_alpha); 14071d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu mInvisibleColumnAlpha = 0f; //getFloat(R.dimen.picker_item_invisible_column_item_alpha); 14171d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu 14271d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu mAlphaAnimDuration = 200; // mContext.getResources().getInteger(R.integer.dialog_animation_duration); 14371d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu 14471d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu mDecelerateInterpolator = new DecelerateInterpolator(2.5F); 14571d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu mAccelerateInterpolator = new AccelerateInterpolator(2.5F); 14671d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu 14771d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu LayoutInflater inflater = LayoutInflater.from(getContext()); 148b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu mRootView = (ViewGroup) inflater.inflate(R.layout.lb_picker, this, true); 149b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu mPickerView = (ViewGroup) mRootView.findViewById(R.id.picker); 15071d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu 15171d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu } 15271d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu 15371d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu /** 15471d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu * Get nth PickerColumn. 15571d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu * @param colIndex Index of PickerColumn. 156b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu * @return PickerColumn at colIndex or null if {@link #setColumns(List)} is not called yet. 15771d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu */ 15871d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu public PickerColumn getColumnAt(int colIndex) { 15971d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu if (mColumns == null) { 16071d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu return null; 16171d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu } 16271d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu return mColumns.get(colIndex); 16371d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu } 16471d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu 16571d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu /** 16671d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu * Get number of PickerColumns. 167b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu * @return Number of PickerColumns or 0 if {@link #setColumns(List)} is not called yet. 16871d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu */ 16971d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu public int getColumnsCount() { 17071d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu if (mColumns == null) { 17171d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu return 0; 17271d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu } 17371d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu return mColumns.size(); 17471d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu } 17571d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu 17671d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu /** 177b19799d69cbbe7f7ca104520e9b07312ab7539afDake Gu * Set columns and create Views. 17871d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu * @param columns PickerColumns to be shown in the Picker. 17971d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu */ 180b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu public void setColumns(List<PickerColumn> columns) { 181b19799d69cbbe7f7ca104520e9b07312ab7539afDake Gu mColumnViews.clear(); 182b19799d69cbbe7f7ca104520e9b07312ab7539afDake Gu mPickerView.removeAllViews(); 183b19799d69cbbe7f7ca104520e9b07312ab7539afDake Gu mColumns = new ArrayList<PickerColumn>(columns); 184b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu if (mSelectedColumn > mColumns.size() - 1) { 185b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu mSelectedColumn = mColumns.size() - 1; 18671d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu } 18771d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu LayoutInflater inflater = LayoutInflater.from(getContext()); 18871d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu int totalCol = getColumnsCount(); 18971d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu for (int i = 0; i < totalCol; i++) { 19071d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu final int colIndex = i; 19171d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu final VerticalGridView columnView = (VerticalGridView) inflater.inflate( 19271d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu R.layout.lb_picker_column, mPickerView, false); 1932e42db84057616ff5fc755ab55debef731015d3aDake Gu // we dont want VerticalGridView to receive focus. 1942e42db84057616ff5fc755ab55debef731015d3aDake Gu updateColumnSize(columnView); 1952e42db84057616ff5fc755ab55debef731015d3aDake Gu // always center aligned, not aligning selected item on top/bottom edge. 19671d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu columnView.setWindowAlignment(VerticalGridView.WINDOW_ALIGN_NO_EDGE); 1972e42db84057616ff5fc755ab55debef731015d3aDake Gu // Width is dynamic, so has fixed size is false. 19871d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu columnView.setHasFixedSize(false); 19971d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu mColumnViews.add(columnView); 20071d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu 20171d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu // add view to root 20271d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu mPickerView.addView(columnView); 20371d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu 20471d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu // add a separator if not the last element 20571d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu if (i != totalCol - 1 && getSeparator() != null) { 20671d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu TextView separator = (TextView) inflater.inflate( 207b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu R.layout.lb_picker_separator, mPickerView, false); 20871d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu separator.setText(getSeparator()); 20971d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu mPickerView.addView(separator); 21071d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu } 21171d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu 21271d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu columnView.setAdapter(new PickerScrollArrayAdapter(getContext(), 21371d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu getPickerItemLayoutId(), getPickerItemTextViewId(), colIndex)); 21471d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu columnView.setOnChildViewHolderSelectedListener(mColumnChangeListener); 21571d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu } 21671d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu } 21771d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu 21871d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu /** 21971d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu * When column labels change or column range changes, call this function to re-populate the 22034914fd296a56b55c3c6c3183c7b58c4f16ca775Dake Gu * selection list. Note this function cannot be called from RecyclerView layout/scroll pass. 22171d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu * @param columnIndex Index of column to update. 222b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu * @param column New column to update. 22371d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu */ 224b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu public void setColumnAt(int columnIndex, PickerColumn column) { 225b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu mColumns.set(columnIndex, column); 22671d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu VerticalGridView columnView = mColumnViews.get(columnIndex); 22771d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu PickerScrollArrayAdapter adapter = (PickerScrollArrayAdapter) columnView.getAdapter(); 22834914fd296a56b55c3c6c3183c7b58c4f16ca775Dake Gu if (adapter != null) { 22971d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu adapter.notifyDataSetChanged(); 23071d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu } 231942f79291db75ccf6ecd0351d23a444a43dd0501Dake Gu columnView.setSelectedPosition(column.getCurrentValue() - column.getMinValue()); 23271d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu } 23371d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu 23471d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu /** 23571d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu * Manually set current value of a column. The function will update UI and notify listeners. 23671d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu * @param columnIndex Index of column to update. 23771d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu * @param value New value of the column. 23871d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu * @param runAnimation True to scroll to the value or false otherwise. 23971d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu */ 240b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu public void setColumnValue(int columnIndex, int value, boolean runAnimation) { 241b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu PickerColumn column = mColumns.get(columnIndex); 242b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu if (column.getCurrentValue() != value) { 243b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu column.setCurrentValue(value); 24471d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu notifyValueChanged(columnIndex); 24571d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu VerticalGridView columnView = mColumnViews.get(columnIndex); 24671d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu if (columnView != null) { 24771d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu int position = value - mColumns.get(columnIndex).getMinValue(); 24871d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu if (runAnimation) { 24971d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu columnView.setSelectedPositionSmooth(position); 25071d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu } else { 25171d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu columnView.setSelectedPosition(position); 25271d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu } 25371d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu } 25471d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu } 25571d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu } 25671d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu 25771d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu private void notifyValueChanged(int columnIndex) { 25871d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu if (mListeners != null) { 25971d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu for (int i = mListeners.size() - 1; i >= 0; i--) { 26071d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu mListeners.get(i).onValueChanged(this, columnIndex); 26171d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu } 26271d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu } 26371d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu } 26471d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu 265b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu /** 266b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu * Register a callback to be invoked when the picker's value has changed. 267b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu * @param listener The callback to ad 268b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu */ 269b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu public void addOnValueChangedListener(PickerValueListener listener) { 27071d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu if (mListeners == null) { 27171d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu mListeners = new ArrayList<Picker.PickerValueListener>(); 27271d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu } 27371d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu mListeners.add(listener); 27471d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu } 27571d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu 276b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu /** 277b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu * Remove a previously installed value changed callback 278b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu * @param listener The callback to remove. 279b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu */ 280b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu public void removeOnValueChangedListener(PickerValueListener listener) { 28171d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu if (mListeners != null) { 28271d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu mListeners.remove(listener); 28371d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu } 28471d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu } 28571d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu 2862e42db84057616ff5fc755ab55debef731015d3aDake Gu private void updateColumnAlpha(int colIndex, boolean animate) { 2872e42db84057616ff5fc755ab55debef731015d3aDake Gu VerticalGridView column = mColumnViews.get(colIndex); 28871d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu 28971d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu int selected = column.getSelectedPosition(); 29071d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu View item; 29171d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu 29271d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu for (int i = 0; i < column.getAdapter().getItemCount(); i++) { 29371d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu item = column.getLayoutManager().findViewByPosition(i); 29471d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu if (item != null) { 2952e42db84057616ff5fc755ab55debef731015d3aDake Gu setOrAnimateAlpha(item, (selected == i), colIndex, animate); 29671d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu } 29771d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu } 29871d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu } 29971d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu 3002e42db84057616ff5fc755ab55debef731015d3aDake Gu private void setOrAnimateAlpha(View view, boolean selected, int colIndex, 3012e42db84057616ff5fc755ab55debef731015d3aDake Gu boolean animate) { 3020f96ae4965103bade4bebe7776b2ee35cd603112Dake Gu boolean columnShownAsActivated = colIndex == mSelectedColumn || !hasFocus(); 30371d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu if (selected) { 30471d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu // set alpha for main item (selected) in the column 3052e42db84057616ff5fc755ab55debef731015d3aDake Gu if (columnShownAsActivated) { 30671d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu setOrAnimateAlpha(view, animate, mFocusedAlpha, -1, mDecelerateInterpolator); 30771d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu } else { 30871d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu setOrAnimateAlpha(view, animate, mUnfocusedAlpha, -1, mDecelerateInterpolator); 30971d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu } 31071d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu } else { 31171d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu // set alpha for remaining items in the column 3122e42db84057616ff5fc755ab55debef731015d3aDake Gu if (columnShownAsActivated) { 31371d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu setOrAnimateAlpha(view, animate, mVisibleColumnAlpha, -1, mDecelerateInterpolator); 31471d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu } else { 31571d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu setOrAnimateAlpha(view, animate, mInvisibleColumnAlpha, -1, 31671d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu mDecelerateInterpolator); 31771d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu } 31871d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu } 31971d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu } 32071d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu 32171d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu private void setOrAnimateAlpha(View view, boolean animate, float destAlpha, float startAlpha, 32271d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu Interpolator interpolator) { 32371d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu view.animate().cancel(); 32471d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu if (!animate) { 32571d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu view.setAlpha(destAlpha); 32671d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu } else { 32771d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu if (startAlpha >= 0.0f) { 32871d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu // set a start alpha 32971d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu view.setAlpha(startAlpha); 33071d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu } 33171d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu view.animate().alpha(destAlpha) 33271d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu .setDuration(mAlphaAnimDuration).setInterpolator(interpolator) 33371d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu .start(); 33471d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu } 33571d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu } 33671d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu 33771d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu /** 33871d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu * Classes extending {@link Picker} can override this function to supply the 339b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu * behavior when a list has been scrolled. Subclass may call {@link #setColumnValue(int, int, 340b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu * boolean)} and or {@link #setColumnAt(int,PickerColumn)}. Subclass should not directly call 34171d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu * {@link PickerColumn#setCurrentValue(int)} which does not update internal state or notify 34271d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu * listeners. 34371d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu * @param columnIndex index of which column was changed. 34471d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu * @param newValue A new value desired to be set on the column. 34571d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu */ 346b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu public void onColumnValueChanged(int columnIndex, int newValue) { 347b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu PickerColumn column = mColumns.get(columnIndex); 348b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu if (column.getCurrentValue() != newValue) { 349b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu column.setCurrentValue(newValue); 35071d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu notifyValueChanged(columnIndex); 35171d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu } 35271d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu } 35371d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu 35471d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu private float getFloat(int resourceId) { 35571d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu TypedValue buffer = new TypedValue(); 35671d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu getContext().getResources().getValue(resourceId, buffer, true); 35771d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu return buffer.getFloat(); 35871d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu } 35971d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu 36071d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu static class ViewHolder extends RecyclerView.ViewHolder { 36171d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu final TextView textView; 36271d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu 36371d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu ViewHolder(View v, TextView textView) { 36471d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu super(v); 36571d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu this.textView = textView; 36671d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu } 36771d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu } 36871d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu 36971d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu class PickerScrollArrayAdapter extends RecyclerView.Adapter<ViewHolder> { 37071d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu 37171d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu private final int mResource; 37271d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu private final int mColIndex; 37371d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu private final int mTextViewResourceId; 37471d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu private PickerColumn mData; 37571d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu 37671d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu PickerScrollArrayAdapter(Context context, int resource, int textViewResourceId, 37771d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu int colIndex) { 37871d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu mResource = resource; 37971d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu mColIndex = colIndex; 38071d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu mTextViewResourceId = textViewResourceId; 38171d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu mData = mColumns.get(mColIndex); 38271d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu } 38371d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu 3840f96ae4965103bade4bebe7776b2ee35cd603112Dake Gu @Override 38571d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { 38671d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu LayoutInflater inflater = LayoutInflater.from(parent.getContext()); 38771d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu View v = inflater.inflate(mResource, parent, false); 38871d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu TextView textView; 38971d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu if (mTextViewResourceId != 0) { 39071d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu textView = (TextView) v.findViewById(mTextViewResourceId); 39171d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu } else { 39271d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu textView = (TextView) v; 39371d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu } 39471d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu ViewHolder vh = new ViewHolder(v, textView); 39571d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu return vh; 39671d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu } 39771d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu 3980f96ae4965103bade4bebe7776b2ee35cd603112Dake Gu @Override 39971d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu public void onBindViewHolder(ViewHolder holder, int position) { 40071d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu if (holder.textView != null && mData != null) { 401942f79291db75ccf6ecd0351d23a444a43dd0501Dake Gu holder.textView.setText(mData.getLabelFor(mData.getMinValue() + position)); 40271d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu } 40371d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu setOrAnimateAlpha(holder.itemView, 40471d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu (mColumnViews.get(mColIndex).getSelectedPosition() == position), 4052e42db84057616ff5fc755ab55debef731015d3aDake Gu mColIndex, false); 40671d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu } 40771d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu 4080f96ae4965103bade4bebe7776b2ee35cd603112Dake Gu @Override 4090f96ae4965103bade4bebe7776b2ee35cd603112Dake Gu public void onViewAttachedToWindow(ViewHolder holder) { 4100f96ae4965103bade4bebe7776b2ee35cd603112Dake Gu holder.itemView.setFocusable(isActivated()); 4110f96ae4965103bade4bebe7776b2ee35cd603112Dake Gu } 4120f96ae4965103bade4bebe7776b2ee35cd603112Dake Gu 4130f96ae4965103bade4bebe7776b2ee35cd603112Dake Gu @Override 41471d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu public int getItemCount() { 415942f79291db75ccf6ecd0351d23a444a43dd0501Dake Gu return mData == null ? 0 : mData.getCount(); 41671d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu } 41771d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu } 41871d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu 41971d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu private final OnChildViewHolderSelectedListener mColumnChangeListener = new 42071d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu OnChildViewHolderSelectedListener() { 42171d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu 42271d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu @Override 42371d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu public void onChildViewHolderSelected(RecyclerView parent, RecyclerView.ViewHolder child, 42471d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu int position, int subposition) { 42571d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu PickerScrollArrayAdapter pickerScrollArrayAdapter = (PickerScrollArrayAdapter) parent 42671d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu .getAdapter(); 42771d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu 42871d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu int colIndex = mColumnViews.indexOf(parent); 4292e42db84057616ff5fc755ab55debef731015d3aDake Gu updateColumnAlpha(colIndex, true); 43071d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu if (child != null) { 43171d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu int newValue = mColumns.get(colIndex).getMinValue() + position; 432b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu onColumnValueChanged(colIndex, newValue); 43371d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu } 43471d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu } 43571d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu 43671d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu }; 43771d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu 4382e42db84057616ff5fc755ab55debef731015d3aDake Gu @Override 4392e42db84057616ff5fc755ab55debef731015d3aDake Gu public boolean dispatchKeyEvent(android.view.KeyEvent event) { 440b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu if (isActivated()) { 4412e42db84057616ff5fc755ab55debef731015d3aDake Gu final int keyCode = event.getKeyCode(); 4422e42db84057616ff5fc755ab55debef731015d3aDake Gu switch (keyCode) { 4430f96ae4965103bade4bebe7776b2ee35cd603112Dake Gu case KeyEvent.KEYCODE_DPAD_CENTER: 4440f96ae4965103bade4bebe7776b2ee35cd603112Dake Gu case KeyEvent.KEYCODE_ENTER: 4450f96ae4965103bade4bebe7776b2ee35cd603112Dake Gu if (event.getAction() == KeyEvent.ACTION_UP) { 4460f96ae4965103bade4bebe7776b2ee35cd603112Dake Gu performClick(); 4472e42db84057616ff5fc755ab55debef731015d3aDake Gu } 4482e42db84057616ff5fc755ab55debef731015d3aDake Gu break; 4492e42db84057616ff5fc755ab55debef731015d3aDake Gu default: 4502e42db84057616ff5fc755ab55debef731015d3aDake Gu return super.dispatchKeyEvent(event); 4512e42db84057616ff5fc755ab55debef731015d3aDake Gu } 45271d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu return true; 45371d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu } 4542e42db84057616ff5fc755ab55debef731015d3aDake Gu return super.dispatchKeyEvent(event); 4552e42db84057616ff5fc755ab55debef731015d3aDake Gu } 45671d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu 4570f96ae4965103bade4bebe7776b2ee35cd603112Dake Gu @Override 4580f96ae4965103bade4bebe7776b2ee35cd603112Dake Gu protected boolean onRequestFocusInDescendants(int direction, Rect previouslyFocusedRect) { 4590f96ae4965103bade4bebe7776b2ee35cd603112Dake Gu int column = getSelectedColumn(); 4600f96ae4965103bade4bebe7776b2ee35cd603112Dake Gu if (column < mColumnViews.size()) { 4610f96ae4965103bade4bebe7776b2ee35cd603112Dake Gu return mColumnViews.get(column).requestFocus(direction, previouslyFocusedRect); 4620f96ae4965103bade4bebe7776b2ee35cd603112Dake Gu } 4630f96ae4965103bade4bebe7776b2ee35cd603112Dake Gu return false; 4640f96ae4965103bade4bebe7776b2ee35cd603112Dake Gu } 4650f96ae4965103bade4bebe7776b2ee35cd603112Dake Gu 4662e42db84057616ff5fc755ab55debef731015d3aDake Gu /** 4672e42db84057616ff5fc755ab55debef731015d3aDake Gu * Classes extending {@link Picker} can choose to override this method to 4682e42db84057616ff5fc755ab55debef731015d3aDake Gu * supply the {@link Picker}'s column's single item height in pixels. 4692e42db84057616ff5fc755ab55debef731015d3aDake Gu */ 4702e42db84057616ff5fc755ab55debef731015d3aDake Gu protected int getPickerItemHeightPixels() { 4712e42db84057616ff5fc755ab55debef731015d3aDake Gu return getContext().getResources().getDimensionPixelSize(R.dimen.picker_item_height); 4722e42db84057616ff5fc755ab55debef731015d3aDake Gu } 4732e42db84057616ff5fc755ab55debef731015d3aDake Gu 4742e42db84057616ff5fc755ab55debef731015d3aDake Gu private void updateColumnSize() { 4752e42db84057616ff5fc755ab55debef731015d3aDake Gu for (int i = 0; i < getColumnsCount(); i++) { 4762e42db84057616ff5fc755ab55debef731015d3aDake Gu updateColumnSize(mColumnViews.get(i)); 4772e42db84057616ff5fc755ab55debef731015d3aDake Gu } 4782e42db84057616ff5fc755ab55debef731015d3aDake Gu } 4792e42db84057616ff5fc755ab55debef731015d3aDake Gu 4802e42db84057616ff5fc755ab55debef731015d3aDake Gu private void updateColumnSize(VerticalGridView columnView) { 4812e42db84057616ff5fc755ab55debef731015d3aDake Gu ViewGroup.LayoutParams lp = columnView.getLayoutParams(); 482b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu lp.height = (int) (getPickerItemHeightPixels() * (isActivated() ? 483b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu getActivatedVisibleItemCount() : getVisibleItemCount())); 4842e42db84057616ff5fc755ab55debef731015d3aDake Gu columnView.setLayoutParams(lp); 4852e42db84057616ff5fc755ab55debef731015d3aDake Gu } 4862e42db84057616ff5fc755ab55debef731015d3aDake Gu 4870f96ae4965103bade4bebe7776b2ee35cd603112Dake Gu private void updateItemFocusable() { 4880f96ae4965103bade4bebe7776b2ee35cd603112Dake Gu final boolean activated = isActivated(); 4890f96ae4965103bade4bebe7776b2ee35cd603112Dake Gu for (int i = 0; i < getColumnsCount(); i++) { 4900f96ae4965103bade4bebe7776b2ee35cd603112Dake Gu VerticalGridView grid = mColumnViews.get(i); 4910f96ae4965103bade4bebe7776b2ee35cd603112Dake Gu for (int j = 0; j < grid.getChildCount(); j++) { 4920f96ae4965103bade4bebe7776b2ee35cd603112Dake Gu View view = grid.getChildAt(j); 4930f96ae4965103bade4bebe7776b2ee35cd603112Dake Gu view.setFocusable(activated); 4940f96ae4965103bade4bebe7776b2ee35cd603112Dake Gu } 4950f96ae4965103bade4bebe7776b2ee35cd603112Dake Gu } 4960f96ae4965103bade4bebe7776b2ee35cd603112Dake Gu } 4972e42db84057616ff5fc755ab55debef731015d3aDake Gu /** 498b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu * Returns number of visible items showing in a column when it's activated. The default value 499b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu * is 3. 500b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu * @return Number of visible items showing in a column when it's activated. 5012e42db84057616ff5fc755ab55debef731015d3aDake Gu */ 502b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu public float getActivatedVisibleItemCount() { 503b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu return mVisibleItemsActivated; 5042e42db84057616ff5fc755ab55debef731015d3aDake Gu } 5052e42db84057616ff5fc755ab55debef731015d3aDake Gu 5062e42db84057616ff5fc755ab55debef731015d3aDake Gu /** 507b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu * Changes number of visible items showing in a column when it's activated. The default value 508b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu * is 3. 509b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu * @param visiblePickerItems Number of visible items showing in a column when it's activated. 5102e42db84057616ff5fc755ab55debef731015d3aDake Gu */ 511b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu public void setActivatedVisibleItemCount(float visiblePickerItems) { 5122e42db84057616ff5fc755ab55debef731015d3aDake Gu if (visiblePickerItems <= 0) { 5132e42db84057616ff5fc755ab55debef731015d3aDake Gu throw new IllegalArgumentException(); 5142e42db84057616ff5fc755ab55debef731015d3aDake Gu } 515b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu if (mVisibleItemsActivated != visiblePickerItems) { 516b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu mVisibleItemsActivated = visiblePickerItems; 517b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu if (isActivated()) { 5182e42db84057616ff5fc755ab55debef731015d3aDake Gu updateColumnSize(); 5192e42db84057616ff5fc755ab55debef731015d3aDake Gu } 5202e42db84057616ff5fc755ab55debef731015d3aDake Gu } 5212e42db84057616ff5fc755ab55debef731015d3aDake Gu } 5222e42db84057616ff5fc755ab55debef731015d3aDake Gu 5232e42db84057616ff5fc755ab55debef731015d3aDake Gu /** 524b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu * Returns number of visible items showing in a column when it's not activated. The default 525b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu * value is 1. 526b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu * @return Number of visible items showing in a column when it's not activated. 5272e42db84057616ff5fc755ab55debef731015d3aDake Gu */ 528b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu public float getVisibleItemCount() { 5292e42db84057616ff5fc755ab55debef731015d3aDake Gu return 1; 5302e42db84057616ff5fc755ab55debef731015d3aDake Gu } 5312e42db84057616ff5fc755ab55debef731015d3aDake Gu 5322e42db84057616ff5fc755ab55debef731015d3aDake Gu /** 533b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu * Changes number of visible items showing in a column when it's not activated. The default 534b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu * value is 1. 535b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu * @param pickerItems Number of visible items showing in a column when it's not activated. 5362e42db84057616ff5fc755ab55debef731015d3aDake Gu */ 537b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu public void setVisibleItemCount(float pickerItems) { 5382e42db84057616ff5fc755ab55debef731015d3aDake Gu if (pickerItems <= 0) { 5392e42db84057616ff5fc755ab55debef731015d3aDake Gu throw new IllegalArgumentException(); 5402e42db84057616ff5fc755ab55debef731015d3aDake Gu } 5412e42db84057616ff5fc755ab55debef731015d3aDake Gu if (mVisibleItems != pickerItems) { 5422e42db84057616ff5fc755ab55debef731015d3aDake Gu mVisibleItems = pickerItems; 543b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu if (!isActivated()) { 5442e42db84057616ff5fc755ab55debef731015d3aDake Gu updateColumnSize(); 5452e42db84057616ff5fc755ab55debef731015d3aDake Gu } 5462e42db84057616ff5fc755ab55debef731015d3aDake Gu } 5472e42db84057616ff5fc755ab55debef731015d3aDake Gu } 5482e42db84057616ff5fc755ab55debef731015d3aDake Gu 549b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu @Override 550b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu public void setActivated(boolean activated) { 551b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu if (activated != isActivated()) { 552b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu super.setActivated(activated); 5532e42db84057616ff5fc755ab55debef731015d3aDake Gu updateColumnSize(); 5540f96ae4965103bade4bebe7776b2ee35cd603112Dake Gu updateItemFocusable(); 555b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu } else { 556b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu super.setActivated(activated); 5572e42db84057616ff5fc755ab55debef731015d3aDake Gu } 5582e42db84057616ff5fc755ab55debef731015d3aDake Gu } 5592e42db84057616ff5fc755ab55debef731015d3aDake Gu 5600f96ae4965103bade4bebe7776b2ee35cd603112Dake Gu @Override 5610f96ae4965103bade4bebe7776b2ee35cd603112Dake Gu public void requestChildFocus(View child, View focused) { 5620f96ae4965103bade4bebe7776b2ee35cd603112Dake Gu super.requestChildFocus(child, focused); 5630f96ae4965103bade4bebe7776b2ee35cd603112Dake Gu for (int i = 0; i < mColumnViews.size(); i++) { 5640f96ae4965103bade4bebe7776b2ee35cd603112Dake Gu if (mColumnViews.get(i).hasFocus()) { 5650f96ae4965103bade4bebe7776b2ee35cd603112Dake Gu setSelectedColumn(i); 5660f96ae4965103bade4bebe7776b2ee35cd603112Dake Gu } 5670f96ae4965103bade4bebe7776b2ee35cd603112Dake Gu } 5680f96ae4965103bade4bebe7776b2ee35cd603112Dake Gu } 5690f96ae4965103bade4bebe7776b2ee35cd603112Dake Gu 5702e42db84057616ff5fc755ab55debef731015d3aDake Gu /** 571b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu * Change current selected column. Picker shows multiple items on selected column if Picker has 572b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu * focus. Picker shows multiple items on all column if Picker has no focus (e.g. a Touchscreen 5732e42db84057616ff5fc755ab55debef731015d3aDake Gu * screen). 5742e42db84057616ff5fc755ab55debef731015d3aDake Gu * @param columnIndex Index of column to activate. 5752e42db84057616ff5fc755ab55debef731015d3aDake Gu */ 576b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu public void setSelectedColumn(int columnIndex) { 577b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu if (mSelectedColumn != columnIndex) { 578b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu mSelectedColumn = columnIndex; 57971d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu for (int i = 0; i < mColumnViews.size(); i++) { 5802e42db84057616ff5fc755ab55debef731015d3aDake Gu updateColumnAlpha(i, true); 58171d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu } 58271d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu } 5832e42db84057616ff5fc755ab55debef731015d3aDake Gu } 5842e42db84057616ff5fc755ab55debef731015d3aDake Gu 5852e42db84057616ff5fc755ab55debef731015d3aDake Gu /** 5862e42db84057616ff5fc755ab55debef731015d3aDake Gu * Get current activated column index. 5872e42db84057616ff5fc755ab55debef731015d3aDake Gu * @return Current activated column index. 5882e42db84057616ff5fc755ab55debef731015d3aDake Gu */ 589b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu public int getSelectedColumn() { 590b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu return mSelectedColumn; 5912e42db84057616ff5fc755ab55debef731015d3aDake Gu } 59271d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu 59371d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu} 594