YearPickerView.java revision 4e5168fae43e783a35c5bc731e500196005268fb
1/* 2 * Copyright (C) 2014 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17package android.widget; 18 19import android.content.Context; 20import android.content.res.ColorStateList; 21import android.content.res.Resources; 22import android.util.AttributeSet; 23import android.util.StateSet; 24import android.view.View; 25import android.view.ViewGroup; 26import android.view.accessibility.AccessibilityEvent; 27 28import java.util.Calendar; 29 30import com.android.internal.R; 31 32/** 33 * Displays a selectable list of years. 34 */ 35class YearPickerView extends ListView implements AdapterView.OnItemClickListener, 36 OnDateChangedListener { 37 private final Calendar mMinDate = Calendar.getInstance(); 38 private final Calendar mMaxDate = Calendar.getInstance(); 39 40 private final YearAdapter mAdapter; 41 private final int mViewSize; 42 private final int mChildSize; 43 44 private DatePickerController mController; 45 46 private int mSelectedPosition = -1; 47 private int mYearActivatedColor; 48 49 public YearPickerView(Context context) { 50 this(context, null); 51 } 52 53 public YearPickerView(Context context, AttributeSet attrs) { 54 this(context, attrs, R.attr.listViewStyle); 55 } 56 57 public YearPickerView(Context context, AttributeSet attrs, int defStyleAttr) { 58 this(context, attrs, defStyleAttr, 0); 59 } 60 61 public YearPickerView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { 62 super(context, attrs, defStyleAttr, defStyleRes); 63 64 final LayoutParams frame = new LayoutParams( 65 LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT); 66 setLayoutParams(frame); 67 68 final Resources res = context.getResources(); 69 mViewSize = res.getDimensionPixelOffset(R.dimen.datepicker_view_animator_height); 70 mChildSize = res.getDimensionPixelOffset(R.dimen.datepicker_year_label_height); 71 72 setVerticalFadingEdgeEnabled(true); 73 setFadingEdgeLength(mChildSize / 3); 74 75 final int paddingTop = res.getDimensionPixelSize( 76 R.dimen.datepicker_year_picker_padding_top); 77 setPadding(0, paddingTop, 0, 0); 78 79 setOnItemClickListener(this); 80 setDividerHeight(0); 81 82 mAdapter = new YearAdapter(getContext(), R.layout.year_label_text_view); 83 setAdapter(mAdapter); 84 } 85 86 public void setRange(Calendar min, Calendar max) { 87 mMinDate.setTimeInMillis(min.getTimeInMillis()); 88 mMaxDate.setTimeInMillis(max.getTimeInMillis()); 89 90 updateAdapterData(); 91 } 92 93 public void init(DatePickerController controller) { 94 mController = controller; 95 mController.registerOnDateChangedListener(this); 96 97 updateAdapterData(); 98 99 onDateChanged(); 100 } 101 102 public void setYearBackgroundColor(ColorStateList yearBackgroundColor) { 103 mYearActivatedColor = yearBackgroundColor.getColorForState( 104 StateSet.get(StateSet.VIEW_STATE_ENABLED | StateSet.VIEW_STATE_ACTIVATED), 0); 105 invalidate(); 106 } 107 108 public void setYearTextAppearance(int resId) { 109 mAdapter.setItemTextAppearance(resId); 110 } 111 112 private void updateAdapterData() { 113 mAdapter.clear(); 114 115 final int maxYear = mMaxDate.get(Calendar.YEAR); 116 for (int year = mMinDate.get(Calendar.YEAR); year <= maxYear; year++) { 117 mAdapter.add(year); 118 } 119 } 120 121 @Override 122 public void onItemClick(AdapterView<?> parent, View view, int position, long id) { 123 mController.tryVibrate(); 124 if (position != mSelectedPosition) { 125 mSelectedPosition = position; 126 mAdapter.notifyDataSetChanged(); 127 } 128 mController.onYearSelected(mAdapter.getItem(position)); 129 } 130 131 private class YearAdapter extends ArrayAdapter<Integer> { 132 private int mItemTextAppearanceResId; 133 134 public YearAdapter(Context context, int resource) { 135 super(context, resource); 136 } 137 138 @Override 139 public View getView(int position, View convertView, ViewGroup parent) { 140 final TextViewWithCircularIndicator v = (TextViewWithCircularIndicator) 141 super.getView(position, convertView, parent); 142 v.setTextAppearance(v.getContext(), mItemTextAppearanceResId); 143 v.setCircleColor(mYearActivatedColor); 144 145 final int year = getItem(position); 146 final boolean selected = mController.getSelectedDay().get(Calendar.YEAR) == year; 147 v.setActivated(selected); 148 149 return v; 150 } 151 152 public void setItemTextAppearance(int resId) { 153 mItemTextAppearanceResId = resId; 154 } 155 } 156 157 public void postSetSelectionCentered(final int position) { 158 postSetSelectionFromTop(position, mViewSize / 2 - mChildSize / 2); 159 } 160 161 public void postSetSelectionFromTop(final int position, final int offset) { 162 post(new Runnable() { 163 164 @Override 165 public void run() { 166 setSelectionFromTop(position, offset); 167 requestLayout(); 168 } 169 }); 170 } 171 172 public int getFirstPositionOffset() { 173 final View firstChild = getChildAt(0); 174 if (firstChild == null) { 175 return 0; 176 } 177 return firstChild.getTop(); 178 } 179 180 @Override 181 public void onDateChanged() { 182 updateAdapterData(); 183 mAdapter.notifyDataSetChanged(); 184 postSetSelectionCentered( 185 mController.getSelectedDay().get(Calendar.YEAR) - mMinDate.get(Calendar.YEAR)); 186 } 187 188 /** @hide */ 189 @Override 190 public void onInitializeAccessibilityEventInternal(AccessibilityEvent event) { 191 super.onInitializeAccessibilityEventInternal(event); 192 193 if (event.getEventType() == AccessibilityEvent.TYPE_VIEW_SCROLLED) { 194 event.setFromIndex(0); 195 event.setToIndex(0); 196 } 197 } 198}