Picker.java revision b19799d69cbbe7f7ca104520e9b07312ab7539af
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; 1871d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Guimport android.support.v17.leanback.R; 1971d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Guimport android.support.v17.leanback.widget.OnChildViewHolderSelectedListener; 2071d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Guimport android.support.v17.leanback.widget.VerticalGridView; 2171d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Guimport android.support.v7.widget.RecyclerView; 2271d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Guimport android.util.AttributeSet; 2371d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Guimport android.util.TypedValue; 242e42db84057616ff5fc755ab55debef731015d3aDake Guimport android.view.KeyEvent; 2571d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Guimport android.view.LayoutInflater; 2671d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Guimport android.view.View; 2771d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Guimport android.view.ViewGroup; 2871d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Guimport android.view.animation.AccelerateInterpolator; 2971d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Guimport android.view.animation.DecelerateInterpolator; 3071d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Guimport android.view.animation.Interpolator; 3171d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Guimport android.widget.FrameLayout; 3271d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Guimport android.widget.TextView; 3371d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu 3471d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Guimport java.util.ArrayList; 3571d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Guimport java.util.List; 3671d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu 3771d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu/** 38b19799d69cbbe7f7ca104520e9b07312ab7539afDake Gu * Picker is a widget showing multiple customized {@link PickerColumn}s. The PickerColumns are 39b19799d69cbbe7f7ca104520e9b07312ab7539afDake Gu * initialized in {@link #setColumns(ArrayList)}. Call {@link #updateAdapter(int)} if the column 40b19799d69cbbe7f7ca104520e9b07312ab7539afDake Gu * value range or labels change. Call {@link #updateValue(int, int, boolean)} to update the current 41b19799d69cbbe7f7ca104520e9b07312ab7539afDake Gu * value of PickerColumn. 422e42db84057616ff5fc755ab55debef731015d3aDake Gu * <p> 432e42db84057616ff5fc755ab55debef731015d3aDake Gu * Picker has two states and will change height: 442e42db84057616ff5fc755ab55debef731015d3aDake Gu * <li>{@link #isExpanded()} is true: Picker shows typically three items vertically (see 452e42db84057616ff5fc755ab55debef731015d3aDake Gu * {@link #getVisiblePickerItemsInExpand()}}. Columns other than {@link #getActiveColumn()} still 46b19799d69cbbe7f7ca104520e9b07312ab7539afDake Gu * shows one item if the Picker is focused. On a touch screen device, the Picker will not get focus 47b19799d69cbbe7f7ca104520e9b07312ab7539afDake Gu * so it always show three items on all columns. On a non-touch device (a TV), the Picker will show 48b19799d69cbbe7f7ca104520e9b07312ab7539afDake Gu * three items only on currently activated column. If the Picker has focus, it will intercept DPAD 49b19799d69cbbe7f7ca104520e9b07312ab7539afDake Gu * directions and select activated column. 502e42db84057616ff5fc755ab55debef731015d3aDake Gu * <li>{@link #isExpanded()} is false: Picker shows one item vertically (see 51b19799d69cbbe7f7ca104520e9b07312ab7539afDake Gu * {@link #getVisiblePickerItems()}) on all columns. The size of Picker shrinks. 52b19799d69cbbe7f7ca104520e9b07312ab7539afDake Gu * <li>The expand mode will be toggled if the Picker has focus and {@link #isToggleExpandOnClick()} 53b19799d69cbbe7f7ca104520e9b07312ab7539afDake Gu * is true. Summarize Typically use cases: 54b19799d69cbbe7f7ca104520e9b07312ab7539afDake Gu * <li>On a touch screen based device, the Picker focusableInTouchMode=false. It won't get focus, it 55b19799d69cbbe7f7ca104520e9b07312ab7539afDake Gu * wont toggle expand mode on click or touch, should call {@link #setExpanded(boolean)} with true, 56b19799d69cbbe7f7ca104520e9b07312ab7539afDake Gu * so that user always sees three items on all columns. 57b19799d69cbbe7f7ca104520e9b07312ab7539afDake Gu * <li>On a TV: the Picker focusable=true. It will get focus and toggle into expand mode when user 58b19799d69cbbe7f7ca104520e9b07312ab7539afDake Gu * clicks on it, toggle can be disabled by {@link #setToggleExpandOnClick(boolean)} with false. Only 59b19799d69cbbe7f7ca104520e9b07312ab7539afDake Gu * the activated column shows multiple items and the activated column is selected by DPAD left or 60b19799d69cbbe7f7ca104520e9b07312ab7539afDake Gu * right. 6171d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu */ 6271d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gupublic class Picker extends FrameLayout { 6371d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu 6471d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu public interface PickerValueListener { 6571d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu public void onValueChanged(Picker picker, int column); 6671d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu } 6771d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu 6871d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu private String mSeparator; 6971d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu private ViewGroup mRootView; 702e42db84057616ff5fc755ab55debef731015d3aDake Gu private ViewGroup mPickerView; 7171d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu private List<VerticalGridView> mColumnViews = new ArrayList<VerticalGridView>(); 7271d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu private ArrayList<PickerColumn> mColumns; 7371d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu 7471d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu private float mUnfocusedAlpha; 7571d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu private float mFocusedAlpha; 7671d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu private float mVisibleColumnAlpha; 7771d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu private float mInvisibleColumnAlpha; 7871d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu private int mAlphaAnimDuration; 7971d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu private Interpolator mDecelerateInterpolator; 8071d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu private Interpolator mAccelerateInterpolator; 8171d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu private ArrayList<PickerValueListener> mListeners; 822e42db84057616ff5fc755ab55debef731015d3aDake Gu private boolean mExpanded; 832e42db84057616ff5fc755ab55debef731015d3aDake Gu private float mVisibleItemsInExpand = 3; 842e42db84057616ff5fc755ab55debef731015d3aDake Gu private float mVisibleItems = 1; 852e42db84057616ff5fc755ab55debef731015d3aDake Gu private int mActivatedColumn = 0; 862e42db84057616ff5fc755ab55debef731015d3aDake Gu private boolean mToggleExpandOnClick = true; 8771d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu 8871d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu /** 8971d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu * Classes extending {@link Picker} can choose to override this method to 9071d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu * supply the separator string 9171d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu */ 9271d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu protected String getSeparator() { 9371d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu return mSeparator; 9471d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu } 9571d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu 9671d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu /** 9771d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu * Classes extending {@link Picker} can choose to override this method to 9871d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu * supply the {@link Picker}'s root layout id 9971d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu */ 10071d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu protected int getRootLayoutId() { 10171d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu return R.layout.lb_picker; 10271d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu } 10371d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu 10471d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu /** 10571d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu * Classes extending {@link Picker} can choose to override this method to 10671d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu * supply the {@link Picker}'s id from within the layout provided by 10771d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu * {@link Picker#getRootLayoutId()} 10871d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu */ 10971d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu protected int getPickerId() { 11071d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu return R.id.picker; 11171d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu } 11271d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu 11371d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu /** 11471d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu * Classes extending {@link Picker} can choose to override this method to 11571d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu * supply the {@link Picker}'s separator's layout id 11671d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu */ 11771d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu protected int getPickerSeparatorLayoutId() { 11871d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu return R.layout.lb_picker_separator; 11971d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu } 12071d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu 12171d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu /** 12271d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu * Classes extending {@link Picker} can choose to override this method to 12371d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu * supply the {@link Picker}'s item's layout id 12471d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu */ 12571d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu protected int getPickerItemLayoutId() { 12671d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu return R.layout.lb_picker_item; 12771d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu } 12871d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu 12971d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu /** 13071d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu * Classes extending {@link Picker} can choose to override this method to 13171d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu * supply the {@link Picker}'s item's {@link TextView}'s id from within the 13271d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu * layout provided by {@link Picker#getPickerItemLayoutId()} or 0 if the 13371d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu * layout provided by {@link Picker#getPickerItemLayoutId()} is a {link 13471d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu * TextView}. 13571d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu */ 13671d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu protected int getPickerItemTextViewId() { 13771d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu return 0; 13871d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu } 13971d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu 14071d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu /** 14171d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu * Creates a Picker widget. 14271d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu * @param context 14371d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu * @param attrs 14471d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu * @param defStyleAttr 14571d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu */ 14671d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu public Picker(Context context, AttributeSet attrs, int defStyleAttr) { 14771d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu super(context, attrs, defStyleAttr); 1482e42db84057616ff5fc755ab55debef731015d3aDake Gu // On TV, Picker is focusable and intercept Click / DPAD direction keys. We dont want any 1492e42db84057616ff5fc755ab55debef731015d3aDake Gu // child to get focus. On touch screen, Picker is not focusable. 1502e42db84057616ff5fc755ab55debef731015d3aDake Gu setFocusable(true); 1512e42db84057616ff5fc755ab55debef731015d3aDake Gu setDescendantFocusability(ViewGroup.FOCUS_BLOCK_DESCENDANTS); 1522e42db84057616ff5fc755ab55debef731015d3aDake Gu // Make it enabled and clickable to receive Click event. 1532e42db84057616ff5fc755ab55debef731015d3aDake Gu setEnabled(true); 1542e42db84057616ff5fc755ab55debef731015d3aDake Gu setClickable(true); 15571d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu 15671d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu mFocusedAlpha = 1f; //getFloat(R.dimen.list_item_selected_title_text_alpha); 15771d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu mUnfocusedAlpha = 1f; //getFloat(R.dimen.list_item_unselected_text_alpha); 15871d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu mVisibleColumnAlpha = 0.5f; //getFloat(R.dimen.picker_item_visible_column_item_alpha); 15971d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu mInvisibleColumnAlpha = 0f; //getFloat(R.dimen.picker_item_invisible_column_item_alpha); 16071d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu 16171d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu mAlphaAnimDuration = 200; // mContext.getResources().getInteger(R.integer.dialog_animation_duration); 16271d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu 16371d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu mDecelerateInterpolator = new DecelerateInterpolator(2.5F); 16471d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu mAccelerateInterpolator = new AccelerateInterpolator(2.5F); 16571d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu 16671d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu LayoutInflater inflater = LayoutInflater.from(getContext()); 16771d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu mRootView = (ViewGroup) inflater.inflate(getRootLayoutId(), this, true); 1682e42db84057616ff5fc755ab55debef731015d3aDake Gu mPickerView = (ViewGroup) mRootView.findViewById(getPickerId()); 16971d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu 17071d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu } 17171d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu 17271d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu /** 17371d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu * Get nth PickerColumn. 17471d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu * @param colIndex Index of PickerColumn. 17571d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu * @return PickerColumn at colIndex or null if {@link #setColumns(ArrayList)} is not called yet. 17671d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu */ 17771d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu public PickerColumn getColumnAt(int colIndex) { 17871d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu if (mColumns == null) { 17971d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu return null; 18071d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu } 18171d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu return mColumns.get(colIndex); 18271d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu } 18371d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu 18471d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu /** 18571d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu * Get number of PickerColumns. 18671d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu * @return Number of PickerColumns or 0 if {@link #setColumns(ArrayList)} is not called yet. 18771d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu */ 18871d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu public int getColumnsCount() { 18971d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu if (mColumns == null) { 19071d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu return 0; 19171d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu } 19271d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu return mColumns.size(); 19371d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu } 19471d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu 19571d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu /** 196b19799d69cbbe7f7ca104520e9b07312ab7539afDake Gu * Set columns and create Views. 19771d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu * @param columns PickerColumns to be shown in the Picker. 19871d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu */ 19971d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu public void setColumns(ArrayList<PickerColumn> columns) { 200b19799d69cbbe7f7ca104520e9b07312ab7539afDake Gu mColumnViews.clear(); 201b19799d69cbbe7f7ca104520e9b07312ab7539afDake Gu mPickerView.removeAllViews(); 202b19799d69cbbe7f7ca104520e9b07312ab7539afDake Gu mColumns = new ArrayList<PickerColumn>(columns); 203b19799d69cbbe7f7ca104520e9b07312ab7539afDake Gu if (mActivatedColumn > mColumns.size() - 1) { 204b19799d69cbbe7f7ca104520e9b07312ab7539afDake Gu mActivatedColumn = mColumns.size() - 1; 20571d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu } 20671d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu LayoutInflater inflater = LayoutInflater.from(getContext()); 20771d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu int totalCol = getColumnsCount(); 20871d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu for (int i = 0; i < totalCol; i++) { 20971d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu final int colIndex = i; 21071d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu final VerticalGridView columnView = (VerticalGridView) inflater.inflate( 21171d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu R.layout.lb_picker_column, mPickerView, false); 2122e42db84057616ff5fc755ab55debef731015d3aDake Gu // we dont want VerticalGridView to receive focus. 2132e42db84057616ff5fc755ab55debef731015d3aDake Gu columnView.setFocusableInTouchMode(false); 2142e42db84057616ff5fc755ab55debef731015d3aDake Gu columnView.setFocusable(false); 2152e42db84057616ff5fc755ab55debef731015d3aDake Gu updateColumnSize(columnView); 2162e42db84057616ff5fc755ab55debef731015d3aDake Gu // always center aligned, not aligning selected item on top/bottom edge. 21771d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu columnView.setWindowAlignment(VerticalGridView.WINDOW_ALIGN_NO_EDGE); 2182e42db84057616ff5fc755ab55debef731015d3aDake Gu // Width is dynamic, so has fixed size is false. 21971d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu columnView.setHasFixedSize(false); 22071d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu mColumnViews.add(columnView); 22171d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu 22271d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu // add view to root 22371d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu mPickerView.addView(columnView); 22471d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu 22571d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu // add a separator if not the last element 22671d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu if (i != totalCol - 1 && getSeparator() != null) { 22771d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu TextView separator = (TextView) inflater.inflate( 22871d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu getPickerSeparatorLayoutId(), mPickerView, false); 22971d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu separator.setText(getSeparator()); 23071d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu mPickerView.addView(separator); 23171d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu } 23271d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu 23371d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu columnView.setAdapter(new PickerScrollArrayAdapter(getContext(), 23471d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu getPickerItemLayoutId(), getPickerItemTextViewId(), colIndex)); 23571d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu columnView.setOnChildViewHolderSelectedListener(mColumnChangeListener); 23671d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu } 23771d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu } 23871d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu 23971d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu /** 24071d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu * When column labels change or column range changes, call this function to re-populate the 24171d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu * selection list. 24271d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu * @param columnIndex Index of column to update. 24371d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu */ 24471d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu public void updateAdapter(int columnIndex) { 24571d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu VerticalGridView columnView = mColumnViews.get(columnIndex); 24671d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu PickerScrollArrayAdapter adapter = (PickerScrollArrayAdapter) columnView.getAdapter(); 247b19799d69cbbe7f7ca104520e9b07312ab7539afDake Gu if (adapter != null && !columnView.isComputingLayout()) { 24871d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu adapter.notifyDataSetChanged(); 24971d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu } 25071d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu } 25171d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu 25271d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu /** 25371d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu * Manually set current value of a column. The function will update UI and notify listeners. 25471d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu * @param columnIndex Index of column to update. 25571d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu * @param value New value of the column. 25671d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu * @param runAnimation True to scroll to the value or false otherwise. 25771d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu */ 25871d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu public void updateValue(int columnIndex, int value, boolean runAnimation) { 25971d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu if (mColumns.get(columnIndex).setCurrentValue(value)) { 26071d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu notifyValueChanged(columnIndex); 26171d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu VerticalGridView columnView = mColumnViews.get(columnIndex); 26271d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu if (columnView != null) { 26371d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu int position = value - mColumns.get(columnIndex).getMinValue(); 26471d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu if (runAnimation) { 26571d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu columnView.setSelectedPositionSmooth(position); 26671d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu } else { 26771d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu columnView.setSelectedPosition(position); 26871d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu } 26971d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu } 27071d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu } 27171d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu } 27271d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu 27371d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu private void notifyValueChanged(int columnIndex) { 27471d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu if (mListeners != null) { 27571d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu for (int i = mListeners.size() - 1; i >= 0; i--) { 27671d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu mListeners.get(i).onValueChanged(this, columnIndex); 27771d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu } 27871d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu } 27971d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu } 28071d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu 28171d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu public void addPickerValueListener(PickerValueListener listener) { 28271d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu if (mListeners == null) { 28371d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu mListeners = new ArrayList<Picker.PickerValueListener>(); 28471d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu } 28571d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu mListeners.add(listener); 28671d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu } 28771d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu 28871d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu public void removePickerValueListener(PickerValueListener listener) { 28971d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu if (mListeners != null) { 29071d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu mListeners.remove(listener); 29171d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu } 29271d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu } 29371d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu 2942e42db84057616ff5fc755ab55debef731015d3aDake Gu private void updateColumnAlpha(int colIndex, boolean animate) { 2952e42db84057616ff5fc755ab55debef731015d3aDake Gu VerticalGridView column = mColumnViews.get(colIndex); 29671d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu 29771d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu int selected = column.getSelectedPosition(); 29871d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu View item; 29971d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu 30071d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu for (int i = 0; i < column.getAdapter().getItemCount(); i++) { 30171d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu item = column.getLayoutManager().findViewByPosition(i); 30271d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu if (item != null) { 3032e42db84057616ff5fc755ab55debef731015d3aDake Gu setOrAnimateAlpha(item, (selected == i), colIndex, animate); 30471d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu } 30571d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu } 30671d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu } 30771d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu 3082e42db84057616ff5fc755ab55debef731015d3aDake Gu private void setOrAnimateAlpha(View view, boolean selected, int colIndex, 3092e42db84057616ff5fc755ab55debef731015d3aDake Gu boolean animate) { 3102e42db84057616ff5fc755ab55debef731015d3aDake Gu boolean columnShownAsActivated = colIndex == mActivatedColumn || !isFocused(); 31171d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu if (selected) { 31271d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu // set alpha for main item (selected) in the column 3132e42db84057616ff5fc755ab55debef731015d3aDake Gu if (columnShownAsActivated) { 31471d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu setOrAnimateAlpha(view, animate, mFocusedAlpha, -1, mDecelerateInterpolator); 31571d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu } else { 31671d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu setOrAnimateAlpha(view, animate, mUnfocusedAlpha, -1, mDecelerateInterpolator); 31771d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu } 31871d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu } else { 31971d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu // set alpha for remaining items in the column 3202e42db84057616ff5fc755ab55debef731015d3aDake Gu if (columnShownAsActivated) { 32171d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu setOrAnimateAlpha(view, animate, mVisibleColumnAlpha, -1, mDecelerateInterpolator); 32271d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu } else { 32371d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu setOrAnimateAlpha(view, animate, mInvisibleColumnAlpha, -1, 32471d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu mDecelerateInterpolator); 32571d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu } 32671d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu } 32771d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu } 32871d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu 32971d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu private void setOrAnimateAlpha(View view, boolean animate, float destAlpha, float startAlpha, 33071d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu Interpolator interpolator) { 33171d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu view.animate().cancel(); 33271d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu if (!animate) { 33371d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu view.setAlpha(destAlpha); 33471d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu } else { 33571d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu if (startAlpha >= 0.0f) { 33671d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu // set a start alpha 33771d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu view.setAlpha(startAlpha); 33871d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu } 33971d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu view.animate().alpha(destAlpha) 34071d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu .setDuration(mAlphaAnimDuration).setInterpolator(interpolator) 34171d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu .start(); 34271d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu } 34371d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu } 34471d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu 34571d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu /** 34671d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu * Classes extending {@link Picker} can override this function to supply the 34771d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu * behavior when a list has been scrolled. Subclass may call {@link #updateValue(int, int, 34871d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu * boolean)} and or {@link #updateAdapter(int)}. Subclass should not directly call 34971d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu * {@link PickerColumn#setCurrentValue(int)} which does not update internal state or notify 35071d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu * listeners. 35171d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu * @param columnIndex index of which column was changed. 35271d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu * @param newValue A new value desired to be set on the column. 35371d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu */ 35471d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu public void onColumnValueChange(int columnIndex, int newValue) { 35571d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu if (mColumns.get(columnIndex).setCurrentValue(newValue)) { 35671d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu notifyValueChanged(columnIndex); 35771d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu } 35871d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu } 35971d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu 36071d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu private float getFloat(int resourceId) { 36171d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu TypedValue buffer = new TypedValue(); 36271d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu getContext().getResources().getValue(resourceId, buffer, true); 36371d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu return buffer.getFloat(); 36471d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu } 36571d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu 36671d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu static class ViewHolder extends RecyclerView.ViewHolder { 36771d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu final TextView textView; 36871d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu 36971d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu ViewHolder(View v, TextView textView) { 37071d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu super(v); 37171d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu this.textView = textView; 37271d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu } 37371d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu } 37471d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu 37571d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu class PickerScrollArrayAdapter extends RecyclerView.Adapter<ViewHolder> { 37671d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu 37771d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu private final int mResource; 37871d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu private final int mColIndex; 37971d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu private final int mTextViewResourceId; 38071d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu private PickerColumn mData; 38171d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu 38271d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu PickerScrollArrayAdapter(Context context, int resource, int textViewResourceId, 38371d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu int colIndex) { 38471d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu mResource = resource; 38571d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu mColIndex = colIndex; 38671d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu mTextViewResourceId = textViewResourceId; 38771d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu mData = mColumns.get(mColIndex); 38871d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu } 38971d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu 39071d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { 39171d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu LayoutInflater inflater = LayoutInflater.from(parent.getContext()); 39271d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu View v = inflater.inflate(mResource, parent, false); 39371d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu TextView textView; 39471d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu if (mTextViewResourceId != 0) { 39571d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu textView = (TextView) v.findViewById(mTextViewResourceId); 39671d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu } else { 39771d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu textView = (TextView) v; 39871d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu } 39971d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu ViewHolder vh = new ViewHolder(v, textView); 40071d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu return vh; 40171d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu } 40271d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu 40371d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu public void onBindViewHolder(ViewHolder holder, int position) { 40471d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu if (holder.textView != null && mData != null) { 40571d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu holder.textView.setText(mData.getValueLabelAt(mData.getMinValue() + position)); 40671d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu } 40771d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu setOrAnimateAlpha(holder.itemView, 40871d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu (mColumnViews.get(mColIndex).getSelectedPosition() == position), 4092e42db84057616ff5fc755ab55debef731015d3aDake Gu mColIndex, false); 41071d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu } 41171d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu 41271d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu public void setData(PickerColumn data) { 41371d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu mData = data; 41471d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu notifyDataSetChanged(); 41571d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu } 41671d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu 41771d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu public int getItemCount() { 41871d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu return mData == null ? 0 : mData.getItemsCount(); 41971d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu } 42071d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu } 42171d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu 42271d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu private final OnChildViewHolderSelectedListener mColumnChangeListener = new 42371d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu OnChildViewHolderSelectedListener() { 42471d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu 42571d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu @Override 42671d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu public void onChildViewHolderSelected(RecyclerView parent, RecyclerView.ViewHolder child, 42771d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu int position, int subposition) { 42871d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu PickerScrollArrayAdapter pickerScrollArrayAdapter = (PickerScrollArrayAdapter) parent 42971d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu .getAdapter(); 43071d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu 43171d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu int colIndex = mColumnViews.indexOf(parent); 4322e42db84057616ff5fc755ab55debef731015d3aDake Gu updateColumnAlpha(colIndex, true); 43371d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu if (child != null) { 43471d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu int newValue = mColumns.get(colIndex).getMinValue() + position; 43571d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu onColumnValueChange(colIndex, newValue); 43671d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu } 43771d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu } 43871d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu 43971d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu }; 44071d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu 4412e42db84057616ff5fc755ab55debef731015d3aDake Gu @Override 4422e42db84057616ff5fc755ab55debef731015d3aDake Gu public boolean dispatchKeyEvent(android.view.KeyEvent event) { 4432e42db84057616ff5fc755ab55debef731015d3aDake Gu if (isExpanded()) { 4442e42db84057616ff5fc755ab55debef731015d3aDake Gu final int keyCode = event.getKeyCode(); 4452e42db84057616ff5fc755ab55debef731015d3aDake Gu switch (keyCode) { 4462e42db84057616ff5fc755ab55debef731015d3aDake Gu case KeyEvent.KEYCODE_DPAD_LEFT: 4472e42db84057616ff5fc755ab55debef731015d3aDake Gu case KeyEvent.KEYCODE_DPAD_RIGHT: 4482e42db84057616ff5fc755ab55debef731015d3aDake Gu if (event.getAction() == KeyEvent.ACTION_DOWN) { 4492e42db84057616ff5fc755ab55debef731015d3aDake Gu if (getLayoutDirection() == View.LAYOUT_DIRECTION_RTL? 4502e42db84057616ff5fc755ab55debef731015d3aDake Gu keyCode == KeyEvent.KEYCODE_DPAD_LEFT : 4512e42db84057616ff5fc755ab55debef731015d3aDake Gu keyCode == KeyEvent.KEYCODE_DPAD_RIGHT ) { 4522e42db84057616ff5fc755ab55debef731015d3aDake Gu if (mActivatedColumn < getColumnsCount() - 1) { 4532e42db84057616ff5fc755ab55debef731015d3aDake Gu setActiveColumn(mActivatedColumn + 1); 4542e42db84057616ff5fc755ab55debef731015d3aDake Gu } 4552e42db84057616ff5fc755ab55debef731015d3aDake Gu } else { 4562e42db84057616ff5fc755ab55debef731015d3aDake Gu if (mActivatedColumn > 0) { 4572e42db84057616ff5fc755ab55debef731015d3aDake Gu setActiveColumn(mActivatedColumn - 1); 4582e42db84057616ff5fc755ab55debef731015d3aDake Gu } 4592e42db84057616ff5fc755ab55debef731015d3aDake Gu } 4602e42db84057616ff5fc755ab55debef731015d3aDake Gu } 4612e42db84057616ff5fc755ab55debef731015d3aDake Gu break; 4622e42db84057616ff5fc755ab55debef731015d3aDake Gu case KeyEvent.KEYCODE_DPAD_UP: 4632e42db84057616ff5fc755ab55debef731015d3aDake Gu case KeyEvent.KEYCODE_DPAD_DOWN: 4642e42db84057616ff5fc755ab55debef731015d3aDake Gu if (event.getAction() == KeyEvent.ACTION_DOWN && mActivatedColumn >= 0) { 4652e42db84057616ff5fc755ab55debef731015d3aDake Gu VerticalGridView gridView = mColumnViews.get(mActivatedColumn); 4662e42db84057616ff5fc755ab55debef731015d3aDake Gu if (keyCode == KeyEvent.KEYCODE_DPAD_UP) { 4672e42db84057616ff5fc755ab55debef731015d3aDake Gu int newPosition = gridView.getSelectedPosition() - 1; 4682e42db84057616ff5fc755ab55debef731015d3aDake Gu if (newPosition >= 0) { 4692e42db84057616ff5fc755ab55debef731015d3aDake Gu gridView.setSelectedPositionSmooth(newPosition); 4702e42db84057616ff5fc755ab55debef731015d3aDake Gu } 4712e42db84057616ff5fc755ab55debef731015d3aDake Gu } else { 4722e42db84057616ff5fc755ab55debef731015d3aDake Gu int newPosition = gridView.getSelectedPosition() + 1; 4732e42db84057616ff5fc755ab55debef731015d3aDake Gu if (newPosition < gridView.getAdapter().getItemCount()) { 4742e42db84057616ff5fc755ab55debef731015d3aDake Gu gridView.setSelectedPositionSmooth(newPosition); 4752e42db84057616ff5fc755ab55debef731015d3aDake Gu } 4762e42db84057616ff5fc755ab55debef731015d3aDake Gu } 4772e42db84057616ff5fc755ab55debef731015d3aDake Gu } 4782e42db84057616ff5fc755ab55debef731015d3aDake Gu break; 4792e42db84057616ff5fc755ab55debef731015d3aDake Gu default: 4802e42db84057616ff5fc755ab55debef731015d3aDake Gu return super.dispatchKeyEvent(event); 4812e42db84057616ff5fc755ab55debef731015d3aDake Gu } 48271d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu return true; 48371d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu } 4842e42db84057616ff5fc755ab55debef731015d3aDake Gu return super.dispatchKeyEvent(event); 4852e42db84057616ff5fc755ab55debef731015d3aDake Gu } 48671d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu 4872e42db84057616ff5fc755ab55debef731015d3aDake Gu /** 4882e42db84057616ff5fc755ab55debef731015d3aDake Gu * Classes extending {@link Picker} can choose to override this method to 4892e42db84057616ff5fc755ab55debef731015d3aDake Gu * supply the {@link Picker}'s column's single item height in pixels. 4902e42db84057616ff5fc755ab55debef731015d3aDake Gu */ 4912e42db84057616ff5fc755ab55debef731015d3aDake Gu protected int getPickerItemHeightPixels() { 4922e42db84057616ff5fc755ab55debef731015d3aDake Gu return getContext().getResources().getDimensionPixelSize(R.dimen.picker_item_height); 4932e42db84057616ff5fc755ab55debef731015d3aDake Gu } 4942e42db84057616ff5fc755ab55debef731015d3aDake Gu 4952e42db84057616ff5fc755ab55debef731015d3aDake Gu private void updateColumnSize() { 4962e42db84057616ff5fc755ab55debef731015d3aDake Gu for (int i = 0; i < getColumnsCount(); i++) { 4972e42db84057616ff5fc755ab55debef731015d3aDake Gu updateColumnSize(mColumnViews.get(i)); 4982e42db84057616ff5fc755ab55debef731015d3aDake Gu } 4992e42db84057616ff5fc755ab55debef731015d3aDake Gu } 5002e42db84057616ff5fc755ab55debef731015d3aDake Gu 5012e42db84057616ff5fc755ab55debef731015d3aDake Gu private void updateColumnSize(VerticalGridView columnView) { 5022e42db84057616ff5fc755ab55debef731015d3aDake Gu ViewGroup.LayoutParams lp = columnView.getLayoutParams(); 5032e42db84057616ff5fc755ab55debef731015d3aDake Gu lp.height = (int) (getPickerItemHeightPixels() * (isExpanded() ? 5042e42db84057616ff5fc755ab55debef731015d3aDake Gu getVisiblePickerItemsInExpand() : getVisiblePickerItems())); 5052e42db84057616ff5fc755ab55debef731015d3aDake Gu columnView.setLayoutParams(lp); 5062e42db84057616ff5fc755ab55debef731015d3aDake Gu } 5072e42db84057616ff5fc755ab55debef731015d3aDake Gu 5082e42db84057616ff5fc755ab55debef731015d3aDake Gu /** 5092e42db84057616ff5fc755ab55debef731015d3aDake Gu * Returns number of visible items showing in a column when it's expanded, it's 3 by default. 5102e42db84057616ff5fc755ab55debef731015d3aDake Gu * @return Number of visible items showing in a column when it's expanded. 5112e42db84057616ff5fc755ab55debef731015d3aDake Gu */ 5122e42db84057616ff5fc755ab55debef731015d3aDake Gu public float getVisiblePickerItemsInExpand() { 5132e42db84057616ff5fc755ab55debef731015d3aDake Gu return mVisibleItemsInExpand; 5142e42db84057616ff5fc755ab55debef731015d3aDake Gu } 5152e42db84057616ff5fc755ab55debef731015d3aDake Gu 5162e42db84057616ff5fc755ab55debef731015d3aDake Gu /** 5172e42db84057616ff5fc755ab55debef731015d3aDake Gu * Change number of visible items showing in a column when it's expanded. 5182e42db84057616ff5fc755ab55debef731015d3aDake Gu * @param visiblePickerItems Number of visible items showing in a column when it's expanded. 5192e42db84057616ff5fc755ab55debef731015d3aDake Gu */ 5202e42db84057616ff5fc755ab55debef731015d3aDake Gu public void setVisiblePickerItemsInExpand(float visiblePickerItems) { 5212e42db84057616ff5fc755ab55debef731015d3aDake Gu if (visiblePickerItems <= 0) { 5222e42db84057616ff5fc755ab55debef731015d3aDake Gu throw new IllegalArgumentException(); 5232e42db84057616ff5fc755ab55debef731015d3aDake Gu } 5242e42db84057616ff5fc755ab55debef731015d3aDake Gu if (mVisibleItemsInExpand != visiblePickerItems) { 5252e42db84057616ff5fc755ab55debef731015d3aDake Gu mVisibleItemsInExpand = visiblePickerItems; 5262e42db84057616ff5fc755ab55debef731015d3aDake Gu if (isExpanded()) { 5272e42db84057616ff5fc755ab55debef731015d3aDake Gu updateColumnSize(); 5282e42db84057616ff5fc755ab55debef731015d3aDake Gu } 5292e42db84057616ff5fc755ab55debef731015d3aDake Gu } 5302e42db84057616ff5fc755ab55debef731015d3aDake Gu } 5312e42db84057616ff5fc755ab55debef731015d3aDake Gu 5322e42db84057616ff5fc755ab55debef731015d3aDake Gu /** 5332e42db84057616ff5fc755ab55debef731015d3aDake Gu * Returns number of visible items showing in a column when it's not expanded, it's 1 by 5342e42db84057616ff5fc755ab55debef731015d3aDake Gu * default. 5352e42db84057616ff5fc755ab55debef731015d3aDake Gu * @return Number of visible items showing in a column when it's not expanded. 5362e42db84057616ff5fc755ab55debef731015d3aDake Gu */ 5372e42db84057616ff5fc755ab55debef731015d3aDake Gu public float getVisiblePickerItems() { 5382e42db84057616ff5fc755ab55debef731015d3aDake Gu return 1; 5392e42db84057616ff5fc755ab55debef731015d3aDake Gu } 5402e42db84057616ff5fc755ab55debef731015d3aDake Gu 5412e42db84057616ff5fc755ab55debef731015d3aDake Gu /** 5422e42db84057616ff5fc755ab55debef731015d3aDake Gu * Change number of visible items showing in a column when it's not expanded, it's 1 by default. 5432e42db84057616ff5fc755ab55debef731015d3aDake Gu * @param pickerItems Number of visible items showing in a column when it's not expanded. 5442e42db84057616ff5fc755ab55debef731015d3aDake Gu */ 5452e42db84057616ff5fc755ab55debef731015d3aDake Gu public void setVisiblePickerItems(float pickerItems) { 5462e42db84057616ff5fc755ab55debef731015d3aDake Gu if (pickerItems <= 0) { 5472e42db84057616ff5fc755ab55debef731015d3aDake Gu throw new IllegalArgumentException(); 5482e42db84057616ff5fc755ab55debef731015d3aDake Gu } 5492e42db84057616ff5fc755ab55debef731015d3aDake Gu if (mVisibleItems != pickerItems) { 5502e42db84057616ff5fc755ab55debef731015d3aDake Gu mVisibleItems = pickerItems; 5512e42db84057616ff5fc755ab55debef731015d3aDake Gu if (!isExpanded()) { 5522e42db84057616ff5fc755ab55debef731015d3aDake Gu updateColumnSize(); 5532e42db84057616ff5fc755ab55debef731015d3aDake Gu } 5542e42db84057616ff5fc755ab55debef731015d3aDake Gu } 5552e42db84057616ff5fc755ab55debef731015d3aDake Gu } 5562e42db84057616ff5fc755ab55debef731015d3aDake Gu 5572e42db84057616ff5fc755ab55debef731015d3aDake Gu /** 5582e42db84057616ff5fc755ab55debef731015d3aDake Gu * Change expanded state of Picker, the height LayoutParams will be changed. 5592e42db84057616ff5fc755ab55debef731015d3aDake Gu * @see #getVisiblePickerItemsInExpand() 5602e42db84057616ff5fc755ab55debef731015d3aDake Gu * @see #getVisiblePickerItems() 5612e42db84057616ff5fc755ab55debef731015d3aDake Gu * @param expanded New expanded state of Picker. 5622e42db84057616ff5fc755ab55debef731015d3aDake Gu */ 5632e42db84057616ff5fc755ab55debef731015d3aDake Gu public void setExpanded(boolean expanded) { 5642e42db84057616ff5fc755ab55debef731015d3aDake Gu if (mExpanded != expanded) { 5652e42db84057616ff5fc755ab55debef731015d3aDake Gu mExpanded = expanded; 5662e42db84057616ff5fc755ab55debef731015d3aDake Gu updateColumnSize(); 5672e42db84057616ff5fc755ab55debef731015d3aDake Gu } 5682e42db84057616ff5fc755ab55debef731015d3aDake Gu } 5692e42db84057616ff5fc755ab55debef731015d3aDake Gu 5702e42db84057616ff5fc755ab55debef731015d3aDake Gu /** 5712e42db84057616ff5fc755ab55debef731015d3aDake Gu * Returns true if the Picker is currently expanded, false otherwise. 5722e42db84057616ff5fc755ab55debef731015d3aDake Gu * @return True if the Picker is currently expanded, false otherwise. 5732e42db84057616ff5fc755ab55debef731015d3aDake Gu */ 5742e42db84057616ff5fc755ab55debef731015d3aDake Gu public boolean isExpanded() { 5752e42db84057616ff5fc755ab55debef731015d3aDake Gu return mExpanded; 5762e42db84057616ff5fc755ab55debef731015d3aDake Gu } 5772e42db84057616ff5fc755ab55debef731015d3aDake Gu 5782e42db84057616ff5fc755ab55debef731015d3aDake Gu /** 5792e42db84057616ff5fc755ab55debef731015d3aDake Gu * Change current activated column. Shows multiple items on activate column if Picker has 5802e42db84057616ff5fc755ab55debef731015d3aDake Gu * focus. Show multiple items on all column if Picker has no focus (e.g. a Touchscreen 5812e42db84057616ff5fc755ab55debef731015d3aDake Gu * screen). 5822e42db84057616ff5fc755ab55debef731015d3aDake Gu * @param columnIndex Index of column to activate. 5832e42db84057616ff5fc755ab55debef731015d3aDake Gu */ 5842e42db84057616ff5fc755ab55debef731015d3aDake Gu public void setActiveColumn(int columnIndex) { 5852e42db84057616ff5fc755ab55debef731015d3aDake Gu if (mActivatedColumn != columnIndex) { 5862e42db84057616ff5fc755ab55debef731015d3aDake Gu mActivatedColumn = columnIndex; 58771d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu for (int i = 0; i < mColumnViews.size(); i++) { 5882e42db84057616ff5fc755ab55debef731015d3aDake Gu updateColumnAlpha(i, true); 58971d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu } 59071d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu } 5912e42db84057616ff5fc755ab55debef731015d3aDake Gu } 5922e42db84057616ff5fc755ab55debef731015d3aDake Gu 5932e42db84057616ff5fc755ab55debef731015d3aDake Gu /** 5942e42db84057616ff5fc755ab55debef731015d3aDake Gu * Get current activated column index. 5952e42db84057616ff5fc755ab55debef731015d3aDake Gu * @return Current activated column index. 5962e42db84057616ff5fc755ab55debef731015d3aDake Gu */ 5972e42db84057616ff5fc755ab55debef731015d3aDake Gu public int getActiveColumn() { 5982e42db84057616ff5fc755ab55debef731015d3aDake Gu return mActivatedColumn; 5992e42db84057616ff5fc755ab55debef731015d3aDake Gu } 6002e42db84057616ff5fc755ab55debef731015d3aDake Gu 6012e42db84057616ff5fc755ab55debef731015d3aDake Gu /** 6022e42db84057616ff5fc755ab55debef731015d3aDake Gu * Enable or disable toggle on click when Picker has focus. 6032e42db84057616ff5fc755ab55debef731015d3aDake Gu * @param toggleExpandOnClick True to enable toggle on click when Picker has focus, false 6042e42db84057616ff5fc755ab55debef731015d3aDake Gu * otherwise. 6052e42db84057616ff5fc755ab55debef731015d3aDake Gu */ 6062e42db84057616ff5fc755ab55debef731015d3aDake Gu public void setToggleExpandOnClick(boolean toggleExpandOnClick) { 6072e42db84057616ff5fc755ab55debef731015d3aDake Gu mToggleExpandOnClick = toggleExpandOnClick; 6082e42db84057616ff5fc755ab55debef731015d3aDake Gu } 6092e42db84057616ff5fc755ab55debef731015d3aDake Gu 6102e42db84057616ff5fc755ab55debef731015d3aDake Gu /** 6112e42db84057616ff5fc755ab55debef731015d3aDake Gu * Returns true if toggle on click is enabled when Picker has focus, false otherwise. 6122e42db84057616ff5fc755ab55debef731015d3aDake Gu * @return True if toggle on click is enabled when Picker has focus, false otherwise. 6132e42db84057616ff5fc755ab55debef731015d3aDake Gu */ 6142e42db84057616ff5fc755ab55debef731015d3aDake Gu public boolean isToggleExpandOnClick() { 6152e42db84057616ff5fc755ab55debef731015d3aDake Gu return mToggleExpandOnClick; 6162e42db84057616ff5fc755ab55debef731015d3aDake Gu } 6172e42db84057616ff5fc755ab55debef731015d3aDake Gu 6182e42db84057616ff5fc755ab55debef731015d3aDake Gu @Override 6192e42db84057616ff5fc755ab55debef731015d3aDake Gu public boolean performClick() { 6202e42db84057616ff5fc755ab55debef731015d3aDake Gu if (isFocused() && isToggleExpandOnClick()) { 6212e42db84057616ff5fc755ab55debef731015d3aDake Gu setExpanded(!isExpanded()); 6222e42db84057616ff5fc755ab55debef731015d3aDake Gu super.performClick(); 6232e42db84057616ff5fc755ab55debef731015d3aDake Gu return true; 6242e42db84057616ff5fc755ab55debef731015d3aDake Gu } 6252e42db84057616ff5fc755ab55debef731015d3aDake Gu return super.performClick(); 6262e42db84057616ff5fc755ab55debef731015d3aDake Gu } 62771d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu 62871d30e1cf5514761ba8ad4bd3c8c70540d60dbd3Dake Gu} 629