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