13e9818e0267619fecebd55095ab26c53eff92e93James Kung/* 23e9818e0267619fecebd55095ab26c53eff92e93James Kung * Copyright (C) 2013 The Android Open Source Project 33e9818e0267619fecebd55095ab26c53eff92e93James Kung * 43e9818e0267619fecebd55095ab26c53eff92e93James Kung * Licensed under the Apache License, Version 2.0 (the "License"); 53e9818e0267619fecebd55095ab26c53eff92e93James Kung * you may not use this file except in compliance with the License. 63e9818e0267619fecebd55095ab26c53eff92e93James Kung * You may obtain a copy of the License at 73e9818e0267619fecebd55095ab26c53eff92e93James Kung * 83e9818e0267619fecebd55095ab26c53eff92e93James Kung * http://www.apache.org/licenses/LICENSE-2.0 93e9818e0267619fecebd55095ab26c53eff92e93James Kung * 103e9818e0267619fecebd55095ab26c53eff92e93James Kung * Unless required by applicable law or agreed to in writing, software 113e9818e0267619fecebd55095ab26c53eff92e93James Kung * distributed under the License is distributed on an "AS IS" BASIS, 123e9818e0267619fecebd55095ab26c53eff92e93James Kung * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 133e9818e0267619fecebd55095ab26c53eff92e93James Kung * See the License for the specific language governing permissions and 143e9818e0267619fecebd55095ab26c53eff92e93James Kung * limitations under the License. 153e9818e0267619fecebd55095ab26c53eff92e93James Kung */ 163e9818e0267619fecebd55095ab26c53eff92e93James Kung 173e9818e0267619fecebd55095ab26c53eff92e93James Kungpackage com.android.datetimepicker.date; 183e9818e0267619fecebd55095ab26c53eff92e93James Kung 193e9818e0267619fecebd55095ab26c53eff92e93James Kungimport android.content.Context; 202e00aa34c051111529290cf23c6ba940c2c0c142James Kungimport android.content.res.Resources; 212e00aa34c051111529290cf23c6ba940c2c0c142James Kungimport android.graphics.drawable.StateListDrawable; 22cb3f2522609186db6239ad154af275957118295cSam Blitzsteinimport android.util.Log; 232e00aa34c051111529290cf23c6ba940c2c0c142James Kungimport android.view.View; 243e9818e0267619fecebd55095ab26c53eff92e93James Kungimport android.view.ViewGroup; 25cb3f2522609186db6239ad154af275957118295cSam Blitzsteinimport android.view.accessibility.AccessibilityEvent; 262e00aa34c051111529290cf23c6ba940c2c0c142James Kungimport android.widget.AdapterView; 272e00aa34c051111529290cf23c6ba940c2c0c142James Kungimport android.widget.AdapterView.OnItemClickListener; 282e00aa34c051111529290cf23c6ba940c2c0c142James Kungimport android.widget.ArrayAdapter; 292e00aa34c051111529290cf23c6ba940c2c0c142James Kungimport android.widget.ListView; 302e00aa34c051111529290cf23c6ba940c2c0c142James Kungimport android.widget.TextView; 312e00aa34c051111529290cf23c6ba940c2c0c142James Kung 322e00aa34c051111529290cf23c6ba940c2c0c142James Kungimport com.android.datetimepicker.R; 33cb3f2522609186db6239ad154af275957118295cSam Blitzsteinimport com.android.datetimepicker.Utils; 342e00aa34c051111529290cf23c6ba940c2c0c142James Kungimport com.android.datetimepicker.date.DatePickerDialog.OnDateChangedListener; 352e00aa34c051111529290cf23c6ba940c2c0c142James Kung 362e00aa34c051111529290cf23c6ba940c2c0c142James Kungimport java.util.ArrayList; 372e00aa34c051111529290cf23c6ba940c2c0c142James Kungimport java.util.List; 383e9818e0267619fecebd55095ab26c53eff92e93James Kung 393e9818e0267619fecebd55095ab26c53eff92e93James Kung/** 402e00aa34c051111529290cf23c6ba940c2c0c142James Kung * Displays a selectable list of years. 413e9818e0267619fecebd55095ab26c53eff92e93James Kung */ 422e00aa34c051111529290cf23c6ba940c2c0c142James Kungpublic class YearPickerView extends ListView implements OnItemClickListener, OnDateChangedListener { 43cb3f2522609186db6239ad154af275957118295cSam Blitzstein private static final String TAG = "YearPickerView"; 443e9818e0267619fecebd55095ab26c53eff92e93James Kung 453e9818e0267619fecebd55095ab26c53eff92e93James Kung private final DatePickerController mController; 462e00aa34c051111529290cf23c6ba940c2c0c142James Kung private YearAdapter mAdapter; 472e00aa34c051111529290cf23c6ba940c2c0c142James Kung private int mViewSize; 482e00aa34c051111529290cf23c6ba940c2c0c142James Kung private int mChildSize; 492e00aa34c051111529290cf23c6ba940c2c0c142James Kung private TextViewWithCircularIndicator mSelectedView; 503e9818e0267619fecebd55095ab26c53eff92e93James Kung 512e00aa34c051111529290cf23c6ba940c2c0c142James Kung /** 522e00aa34c051111529290cf23c6ba940c2c0c142James Kung * @param context 532e00aa34c051111529290cf23c6ba940c2c0c142James Kung */ 543e9818e0267619fecebd55095ab26c53eff92e93James Kung public YearPickerView(Context context, DatePickerController controller) { 553e9818e0267619fecebd55095ab26c53eff92e93James Kung super(context); 563e9818e0267619fecebd55095ab26c53eff92e93James Kung mController = controller; 572e00aa34c051111529290cf23c6ba940c2c0c142James Kung mController.registerOnDateChangedListener(this); 583e9818e0267619fecebd55095ab26c53eff92e93James Kung ViewGroup.LayoutParams frame = new ViewGroup.LayoutParams(LayoutParams.MATCH_PARENT, 593e9818e0267619fecebd55095ab26c53eff92e93James Kung LayoutParams.WRAP_CONTENT); 602e00aa34c051111529290cf23c6ba940c2c0c142James Kung setLayoutParams(frame); 612e00aa34c051111529290cf23c6ba940c2c0c142James Kung Resources res = context.getResources(); 6251da77ac265fc6e46403bc6f8d3cca57e57427d7James Kung mViewSize = res.getDimensionPixelOffset(R.dimen.date_picker_view_animator_height); 632e00aa34c051111529290cf23c6ba940c2c0c142James Kung mChildSize = res.getDimensionPixelOffset(R.dimen.year_label_height); 6451da77ac265fc6e46403bc6f8d3cca57e57427d7James Kung setVerticalFadingEdgeEnabled(true); 652e00aa34c051111529290cf23c6ba940c2c0c142James Kung setFadingEdgeLength(mChildSize / 3); 662e00aa34c051111529290cf23c6ba940c2c0c142James Kung init(context); 672e00aa34c051111529290cf23c6ba940c2c0c142James Kung setOnItemClickListener(this); 682e00aa34c051111529290cf23c6ba940c2c0c142James Kung setSelector(new StateListDrawable()); 692e00aa34c051111529290cf23c6ba940c2c0c142James Kung setDividerHeight(0); 702e00aa34c051111529290cf23c6ba940c2c0c142James Kung onDateChanged(); 712e00aa34c051111529290cf23c6ba940c2c0c142James Kung } 722e00aa34c051111529290cf23c6ba940c2c0c142James Kung 732e00aa34c051111529290cf23c6ba940c2c0c142James Kung private void init(Context context) { 742e00aa34c051111529290cf23c6ba940c2c0c142James Kung ArrayList<String> years = new ArrayList<String>(); 752e00aa34c051111529290cf23c6ba940c2c0c142James Kung for (int year = mController.getMinYear(); year <= mController.getMaxYear(); year++) { 76e0bbee5b271a9439335c002e09a70de8c083568dSam Blitzstein years.add(String.format("%d", year)); 772e00aa34c051111529290cf23c6ba940c2c0c142James Kung } 782e00aa34c051111529290cf23c6ba940c2c0c142James Kung mAdapter = new YearAdapter(context, R.layout.year_label_text_view, years); 792e00aa34c051111529290cf23c6ba940c2c0c142James Kung setAdapter(mAdapter); 802e00aa34c051111529290cf23c6ba940c2c0c142James Kung } 812e00aa34c051111529290cf23c6ba940c2c0c142James Kung 822e00aa34c051111529290cf23c6ba940c2c0c142James Kung @Override 832e00aa34c051111529290cf23c6ba940c2c0c142James Kung public void onItemClick(AdapterView<?> parent, View view, int position, long id) { 842e00aa34c051111529290cf23c6ba940c2c0c142James Kung mController.tryVibrate(); 852e00aa34c051111529290cf23c6ba940c2c0c142James Kung TextViewWithCircularIndicator clickedView = (TextViewWithCircularIndicator) view; 8671492ab60892087f3e989b876b82f5c0249b3b14James Kung if (clickedView != null) { 8771492ab60892087f3e989b876b82f5c0249b3b14James Kung if (clickedView != mSelectedView) { 8871492ab60892087f3e989b876b82f5c0249b3b14James Kung if (mSelectedView != null) { 8971492ab60892087f3e989b876b82f5c0249b3b14James Kung mSelectedView.drawIndicator(false); 9071492ab60892087f3e989b876b82f5c0249b3b14James Kung mSelectedView.requestLayout(); 9171492ab60892087f3e989b876b82f5c0249b3b14James Kung } 9271492ab60892087f3e989b876b82f5c0249b3b14James Kung clickedView.drawIndicator(true); 9371492ab60892087f3e989b876b82f5c0249b3b14James Kung clickedView.requestLayout(); 9471492ab60892087f3e989b876b82f5c0249b3b14James Kung mSelectedView = clickedView; 9571492ab60892087f3e989b876b82f5c0249b3b14James Kung } 9671492ab60892087f3e989b876b82f5c0249b3b14James Kung mController.onYearSelected(getYearFromTextView(clickedView)); 9771492ab60892087f3e989b876b82f5c0249b3b14James Kung mAdapter.notifyDataSetChanged(); 982e00aa34c051111529290cf23c6ba940c2c0c142James Kung } 993e9818e0267619fecebd55095ab26c53eff92e93James Kung } 1003e9818e0267619fecebd55095ab26c53eff92e93James Kung 1012e00aa34c051111529290cf23c6ba940c2c0c142James Kung private int getYearFromTextView(TextView view) { 1022e00aa34c051111529290cf23c6ba940c2c0c142James Kung return Integer.valueOf(view.getText().toString()); 1033e9818e0267619fecebd55095ab26c53eff92e93James Kung } 1043e9818e0267619fecebd55095ab26c53eff92e93James Kung 1052e00aa34c051111529290cf23c6ba940c2c0c142James Kung private class YearAdapter extends ArrayAdapter<String> { 1062e00aa34c051111529290cf23c6ba940c2c0c142James Kung 1072e00aa34c051111529290cf23c6ba940c2c0c142James Kung public YearAdapter(Context context, int resource, List<String> objects) { 1082e00aa34c051111529290cf23c6ba940c2c0c142James Kung super(context, resource, objects); 1092e00aa34c051111529290cf23c6ba940c2c0c142James Kung } 1102e00aa34c051111529290cf23c6ba940c2c0c142James Kung 1112e00aa34c051111529290cf23c6ba940c2c0c142James Kung @Override 1122e00aa34c051111529290cf23c6ba940c2c0c142James Kung public View getView(int position, View convertView, ViewGroup parent) { 1132e00aa34c051111529290cf23c6ba940c2c0c142James Kung TextViewWithCircularIndicator v = (TextViewWithCircularIndicator) 1142e00aa34c051111529290cf23c6ba940c2c0c142James Kung super.getView(position, convertView, parent); 1152e00aa34c051111529290cf23c6ba940c2c0c142James Kung v.requestLayout(); 1162e00aa34c051111529290cf23c6ba940c2c0c142James Kung int year = getYearFromTextView(v); 1172e00aa34c051111529290cf23c6ba940c2c0c142James Kung boolean selected = mController.getSelectedDay().year == year; 1182e00aa34c051111529290cf23c6ba940c2c0c142James Kung v.drawIndicator(selected); 1192e00aa34c051111529290cf23c6ba940c2c0c142James Kung if (selected) { 1202e00aa34c051111529290cf23c6ba940c2c0c142James Kung mSelectedView = v; 1212e00aa34c051111529290cf23c6ba940c2c0c142James Kung } 1222e00aa34c051111529290cf23c6ba940c2c0c142James Kung return v; 1232e00aa34c051111529290cf23c6ba940c2c0c142James Kung } 1242e00aa34c051111529290cf23c6ba940c2c0c142James Kung } 1252e00aa34c051111529290cf23c6ba940c2c0c142James Kung 12671492ab60892087f3e989b876b82f5c0249b3b14James Kung public void postSetSelectionCentered(final int position) { 12771492ab60892087f3e989b876b82f5c0249b3b14James Kung postSetSelectionFromTop(position, mViewSize / 2 - mChildSize / 2); 1282e00aa34c051111529290cf23c6ba940c2c0c142James Kung } 1292e00aa34c051111529290cf23c6ba940c2c0c142James Kung 13071492ab60892087f3e989b876b82f5c0249b3b14James Kung public void postSetSelectionFromTop(final int position, final int offset) { 1312e00aa34c051111529290cf23c6ba940c2c0c142James Kung post(new Runnable() { 1322e00aa34c051111529290cf23c6ba940c2c0c142James Kung 1332e00aa34c051111529290cf23c6ba940c2c0c142James Kung @Override 1342e00aa34c051111529290cf23c6ba940c2c0c142James Kung public void run() { 13571492ab60892087f3e989b876b82f5c0249b3b14James Kung setSelectionFromTop(position, offset); 1362e00aa34c051111529290cf23c6ba940c2c0c142James Kung requestLayout(); 1372e00aa34c051111529290cf23c6ba940c2c0c142James Kung } 1382e00aa34c051111529290cf23c6ba940c2c0c142James Kung }); 1393e9818e0267619fecebd55095ab26c53eff92e93James Kung } 1403e9818e0267619fecebd55095ab26c53eff92e93James Kung 14171492ab60892087f3e989b876b82f5c0249b3b14James Kung public int getFirstPositionOffset() { 14271492ab60892087f3e989b876b82f5c0249b3b14James Kung final View firstChild = getChildAt(0); 14371492ab60892087f3e989b876b82f5c0249b3b14James Kung if (firstChild == null) { 14471492ab60892087f3e989b876b82f5c0249b3b14James Kung return 0; 14571492ab60892087f3e989b876b82f5c0249b3b14James Kung } 14671492ab60892087f3e989b876b82f5c0249b3b14James Kung return firstChild.getTop(); 14771492ab60892087f3e989b876b82f5c0249b3b14James Kung } 14871492ab60892087f3e989b876b82f5c0249b3b14James Kung 1493e9818e0267619fecebd55095ab26c53eff92e93James Kung @Override 1502e00aa34c051111529290cf23c6ba940c2c0c142James Kung public void onDateChanged() { 1512e00aa34c051111529290cf23c6ba940c2c0c142James Kung mAdapter.notifyDataSetChanged(); 15271492ab60892087f3e989b876b82f5c0249b3b14James Kung postSetSelectionCentered(mController.getSelectedDay().year - mController.getMinYear()); 1533e9818e0267619fecebd55095ab26c53eff92e93James Kung } 154cb3f2522609186db6239ad154af275957118295cSam Blitzstein 155cb3f2522609186db6239ad154af275957118295cSam Blitzstein @Override 156cb3f2522609186db6239ad154af275957118295cSam Blitzstein public void onInitializeAccessibilityEvent(AccessibilityEvent event) { 157cb3f2522609186db6239ad154af275957118295cSam Blitzstein super.onInitializeAccessibilityEvent(event); 158cb3f2522609186db6239ad154af275957118295cSam Blitzstein if (event.getEventType() == AccessibilityEvent.TYPE_VIEW_SCROLLED) { 159cb3f2522609186db6239ad154af275957118295cSam Blitzstein event.setFromIndex(0); 160cb3f2522609186db6239ad154af275957118295cSam Blitzstein event.setToIndex(0); 161cb3f2522609186db6239ad154af275957118295cSam Blitzstein } 162cb3f2522609186db6239ad154af275957118295cSam Blitzstein } 1633e9818e0267619fecebd55095ab26c53eff92e93James Kung} 164