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; 222e00aa34c051111529290cf23c6ba940c2c0c142James Kungimport android.view.View; 233e9818e0267619fecebd55095ab26c53eff92e93James Kungimport android.view.ViewGroup; 24cb3f2522609186db6239ad154af275957118295cSam Blitzsteinimport android.view.accessibility.AccessibilityEvent; 252e00aa34c051111529290cf23c6ba940c2c0c142James Kungimport android.widget.AdapterView; 262e00aa34c051111529290cf23c6ba940c2c0c142James Kungimport android.widget.AdapterView.OnItemClickListener; 272e00aa34c051111529290cf23c6ba940c2c0c142James Kungimport android.widget.ArrayAdapter; 282e00aa34c051111529290cf23c6ba940c2c0c142James Kungimport android.widget.ListView; 292e00aa34c051111529290cf23c6ba940c2c0c142James Kungimport android.widget.TextView; 302e00aa34c051111529290cf23c6ba940c2c0c142James Kung 312e00aa34c051111529290cf23c6ba940c2c0c142James Kungimport com.android.datetimepicker.R; 322e00aa34c051111529290cf23c6ba940c2c0c142James Kungimport com.android.datetimepicker.date.DatePickerDialog.OnDateChangedListener; 332e00aa34c051111529290cf23c6ba940c2c0c142James Kung 342e00aa34c051111529290cf23c6ba940c2c0c142James Kungimport java.util.ArrayList; 352e00aa34c051111529290cf23c6ba940c2c0c142James Kungimport java.util.List; 363e9818e0267619fecebd55095ab26c53eff92e93James Kung 373e9818e0267619fecebd55095ab26c53eff92e93James Kung/** 382e00aa34c051111529290cf23c6ba940c2c0c142James Kung * Displays a selectable list of years. 393e9818e0267619fecebd55095ab26c53eff92e93James Kung */ 40a5c1a0a3b7241e3ec567d4fb32673fcfd98d4fc4Alan Viveretteclass YearPickerView extends ListView implements OnItemClickListener, OnDateChangedListener { 41cb3f2522609186db6239ad154af275957118295cSam Blitzstein private static final String TAG = "YearPickerView"; 423e9818e0267619fecebd55095ab26c53eff92e93James Kung 433e9818e0267619fecebd55095ab26c53eff92e93James Kung private final DatePickerController mController; 442e00aa34c051111529290cf23c6ba940c2c0c142James Kung private YearAdapter mAdapter; 452e00aa34c051111529290cf23c6ba940c2c0c142James Kung private int mViewSize; 462e00aa34c051111529290cf23c6ba940c2c0c142James Kung private int mChildSize; 472e00aa34c051111529290cf23c6ba940c2c0c142James Kung private TextViewWithCircularIndicator mSelectedView; 483e9818e0267619fecebd55095ab26c53eff92e93James Kung 492e00aa34c051111529290cf23c6ba940c2c0c142James Kung /** 502e00aa34c051111529290cf23c6ba940c2c0c142James Kung * @param context 512e00aa34c051111529290cf23c6ba940c2c0c142James Kung */ 523e9818e0267619fecebd55095ab26c53eff92e93James Kung public YearPickerView(Context context, DatePickerController controller) { 533e9818e0267619fecebd55095ab26c53eff92e93James Kung super(context); 543e9818e0267619fecebd55095ab26c53eff92e93James Kung mController = controller; 552e00aa34c051111529290cf23c6ba940c2c0c142James Kung mController.registerOnDateChangedListener(this); 563e9818e0267619fecebd55095ab26c53eff92e93James Kung ViewGroup.LayoutParams frame = new ViewGroup.LayoutParams(LayoutParams.MATCH_PARENT, 573e9818e0267619fecebd55095ab26c53eff92e93James Kung LayoutParams.WRAP_CONTENT); 582e00aa34c051111529290cf23c6ba940c2c0c142James Kung setLayoutParams(frame); 592e00aa34c051111529290cf23c6ba940c2c0c142James Kung Resources res = context.getResources(); 6051da77ac265fc6e46403bc6f8d3cca57e57427d7James Kung mViewSize = res.getDimensionPixelOffset(R.dimen.date_picker_view_animator_height); 612e00aa34c051111529290cf23c6ba940c2c0c142James Kung mChildSize = res.getDimensionPixelOffset(R.dimen.year_label_height); 6251da77ac265fc6e46403bc6f8d3cca57e57427d7James Kung setVerticalFadingEdgeEnabled(true); 632e00aa34c051111529290cf23c6ba940c2c0c142James Kung setFadingEdgeLength(mChildSize / 3); 642e00aa34c051111529290cf23c6ba940c2c0c142James Kung init(context); 652e00aa34c051111529290cf23c6ba940c2c0c142James Kung setOnItemClickListener(this); 662e00aa34c051111529290cf23c6ba940c2c0c142James Kung setSelector(new StateListDrawable()); 672e00aa34c051111529290cf23c6ba940c2c0c142James Kung setDividerHeight(0); 682e00aa34c051111529290cf23c6ba940c2c0c142James Kung onDateChanged(); 692e00aa34c051111529290cf23c6ba940c2c0c142James Kung } 702e00aa34c051111529290cf23c6ba940c2c0c142James Kung 712e00aa34c051111529290cf23c6ba940c2c0c142James Kung private void init(Context context) { 722e00aa34c051111529290cf23c6ba940c2c0c142James Kung ArrayList<String> years = new ArrayList<String>(); 732e00aa34c051111529290cf23c6ba940c2c0c142James Kung for (int year = mController.getMinYear(); year <= mController.getMaxYear(); year++) { 74e0bbee5b271a9439335c002e09a70de8c083568dSam Blitzstein years.add(String.format("%d", year)); 752e00aa34c051111529290cf23c6ba940c2c0c142James Kung } 762e00aa34c051111529290cf23c6ba940c2c0c142James Kung mAdapter = new YearAdapter(context, R.layout.year_label_text_view, years); 772e00aa34c051111529290cf23c6ba940c2c0c142James Kung setAdapter(mAdapter); 782e00aa34c051111529290cf23c6ba940c2c0c142James Kung } 792e00aa34c051111529290cf23c6ba940c2c0c142James Kung 802e00aa34c051111529290cf23c6ba940c2c0c142James Kung @Override 812e00aa34c051111529290cf23c6ba940c2c0c142James Kung public void onItemClick(AdapterView<?> parent, View view, int position, long id) { 822e00aa34c051111529290cf23c6ba940c2c0c142James Kung mController.tryVibrate(); 832e00aa34c051111529290cf23c6ba940c2c0c142James Kung TextViewWithCircularIndicator clickedView = (TextViewWithCircularIndicator) view; 8471492ab60892087f3e989b876b82f5c0249b3b14James Kung if (clickedView != null) { 8571492ab60892087f3e989b876b82f5c0249b3b14James Kung if (clickedView != mSelectedView) { 8671492ab60892087f3e989b876b82f5c0249b3b14James Kung if (mSelectedView != null) { 8771492ab60892087f3e989b876b82f5c0249b3b14James Kung mSelectedView.drawIndicator(false); 8871492ab60892087f3e989b876b82f5c0249b3b14James Kung mSelectedView.requestLayout(); 8971492ab60892087f3e989b876b82f5c0249b3b14James Kung } 9071492ab60892087f3e989b876b82f5c0249b3b14James Kung clickedView.drawIndicator(true); 9171492ab60892087f3e989b876b82f5c0249b3b14James Kung clickedView.requestLayout(); 9271492ab60892087f3e989b876b82f5c0249b3b14James Kung mSelectedView = clickedView; 9371492ab60892087f3e989b876b82f5c0249b3b14James Kung } 9471492ab60892087f3e989b876b82f5c0249b3b14James Kung mController.onYearSelected(getYearFromTextView(clickedView)); 9571492ab60892087f3e989b876b82f5c0249b3b14James Kung mAdapter.notifyDataSetChanged(); 962e00aa34c051111529290cf23c6ba940c2c0c142James Kung } 973e9818e0267619fecebd55095ab26c53eff92e93James Kung } 983e9818e0267619fecebd55095ab26c53eff92e93James Kung 99aa0dd58622335c458af9afc0e0656e4664293087Scott Kennedy private static int getYearFromTextView(TextView view) { 10063882b979c54801f2241a5d6cfb0706f9e1e0a31Narayan Kamath return Integer.parseInt(view.getText().toString()); 1013e9818e0267619fecebd55095ab26c53eff92e93James Kung } 1023e9818e0267619fecebd55095ab26c53eff92e93James Kung 1032e00aa34c051111529290cf23c6ba940c2c0c142James Kung private class YearAdapter extends ArrayAdapter<String> { 1042e00aa34c051111529290cf23c6ba940c2c0c142James Kung 1052e00aa34c051111529290cf23c6ba940c2c0c142James Kung public YearAdapter(Context context, int resource, List<String> objects) { 1062e00aa34c051111529290cf23c6ba940c2c0c142James Kung super(context, resource, objects); 1072e00aa34c051111529290cf23c6ba940c2c0c142James Kung } 1082e00aa34c051111529290cf23c6ba940c2c0c142James Kung 1092e00aa34c051111529290cf23c6ba940c2c0c142James Kung @Override 1102e00aa34c051111529290cf23c6ba940c2c0c142James Kung public View getView(int position, View convertView, ViewGroup parent) { 1112e00aa34c051111529290cf23c6ba940c2c0c142James Kung TextViewWithCircularIndicator v = (TextViewWithCircularIndicator) 1122e00aa34c051111529290cf23c6ba940c2c0c142James Kung super.getView(position, convertView, parent); 1132e00aa34c051111529290cf23c6ba940c2c0c142James Kung v.requestLayout(); 1142e00aa34c051111529290cf23c6ba940c2c0c142James Kung int year = getYearFromTextView(v); 1152e00aa34c051111529290cf23c6ba940c2c0c142James Kung boolean selected = mController.getSelectedDay().year == year; 1162e00aa34c051111529290cf23c6ba940c2c0c142James Kung v.drawIndicator(selected); 1172e00aa34c051111529290cf23c6ba940c2c0c142James Kung if (selected) { 1182e00aa34c051111529290cf23c6ba940c2c0c142James Kung mSelectedView = v; 1192e00aa34c051111529290cf23c6ba940c2c0c142James Kung } 1202e00aa34c051111529290cf23c6ba940c2c0c142James Kung return v; 1212e00aa34c051111529290cf23c6ba940c2c0c142James Kung } 1222e00aa34c051111529290cf23c6ba940c2c0c142James Kung } 1232e00aa34c051111529290cf23c6ba940c2c0c142James Kung 12471492ab60892087f3e989b876b82f5c0249b3b14James Kung public void postSetSelectionCentered(final int position) { 12571492ab60892087f3e989b876b82f5c0249b3b14James Kung postSetSelectionFromTop(position, mViewSize / 2 - mChildSize / 2); 1262e00aa34c051111529290cf23c6ba940c2c0c142James Kung } 1272e00aa34c051111529290cf23c6ba940c2c0c142James Kung 12871492ab60892087f3e989b876b82f5c0249b3b14James Kung public void postSetSelectionFromTop(final int position, final int offset) { 1292e00aa34c051111529290cf23c6ba940c2c0c142James Kung post(new Runnable() { 1302e00aa34c051111529290cf23c6ba940c2c0c142James Kung 1312e00aa34c051111529290cf23c6ba940c2c0c142James Kung @Override 1322e00aa34c051111529290cf23c6ba940c2c0c142James Kung public void run() { 13371492ab60892087f3e989b876b82f5c0249b3b14James Kung setSelectionFromTop(position, offset); 1342e00aa34c051111529290cf23c6ba940c2c0c142James Kung requestLayout(); 1352e00aa34c051111529290cf23c6ba940c2c0c142James Kung } 1362e00aa34c051111529290cf23c6ba940c2c0c142James Kung }); 1373e9818e0267619fecebd55095ab26c53eff92e93James Kung } 1383e9818e0267619fecebd55095ab26c53eff92e93James Kung 13971492ab60892087f3e989b876b82f5c0249b3b14James Kung public int getFirstPositionOffset() { 14071492ab60892087f3e989b876b82f5c0249b3b14James Kung final View firstChild = getChildAt(0); 14171492ab60892087f3e989b876b82f5c0249b3b14James Kung if (firstChild == null) { 14271492ab60892087f3e989b876b82f5c0249b3b14James Kung return 0; 14371492ab60892087f3e989b876b82f5c0249b3b14James Kung } 14471492ab60892087f3e989b876b82f5c0249b3b14James Kung return firstChild.getTop(); 14571492ab60892087f3e989b876b82f5c0249b3b14James Kung } 14671492ab60892087f3e989b876b82f5c0249b3b14James Kung 1473e9818e0267619fecebd55095ab26c53eff92e93James Kung @Override 1482e00aa34c051111529290cf23c6ba940c2c0c142James Kung public void onDateChanged() { 1492e00aa34c051111529290cf23c6ba940c2c0c142James Kung mAdapter.notifyDataSetChanged(); 15071492ab60892087f3e989b876b82f5c0249b3b14James Kung postSetSelectionCentered(mController.getSelectedDay().year - mController.getMinYear()); 1513e9818e0267619fecebd55095ab26c53eff92e93James Kung } 152cb3f2522609186db6239ad154af275957118295cSam Blitzstein 153cb3f2522609186db6239ad154af275957118295cSam Blitzstein @Override 154cb3f2522609186db6239ad154af275957118295cSam Blitzstein public void onInitializeAccessibilityEvent(AccessibilityEvent event) { 155cb3f2522609186db6239ad154af275957118295cSam Blitzstein super.onInitializeAccessibilityEvent(event); 156cb3f2522609186db6239ad154af275957118295cSam Blitzstein if (event.getEventType() == AccessibilityEvent.TYPE_VIEW_SCROLLED) { 157cb3f2522609186db6239ad154af275957118295cSam Blitzstein event.setFromIndex(0); 158cb3f2522609186db6239ad154af275957118295cSam Blitzstein event.setToIndex(0); 159cb3f2522609186db6239ad154af275957118295cSam Blitzstein } 160cb3f2522609186db6239ad154af275957118295cSam Blitzstein } 1613e9818e0267619fecebd55095ab26c53eff92e93James Kung} 162