258 lines
7.8 KiB
Java
258 lines
7.8 KiB
Java
/*
|
|
* Copyright (C) 2014 The Android Open Source Project
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
|
|
package android.widget;
|
|
|
|
import android.content.Context;
|
|
import android.content.res.Resources;
|
|
import android.icu.util.Calendar;
|
|
import android.util.AttributeSet;
|
|
import android.view.LayoutInflater;
|
|
import android.view.View;
|
|
import android.view.ViewGroup;
|
|
import android.view.accessibility.AccessibilityEvent;
|
|
|
|
import com.android.internal.R;
|
|
|
|
/**
|
|
* Displays a selectable list of years.
|
|
*/
|
|
class YearPickerView extends ListView {
|
|
private final YearAdapter mAdapter;
|
|
private final int mViewSize;
|
|
private final int mChildSize;
|
|
|
|
private OnYearSelectedListener mOnYearSelectedListener;
|
|
|
|
public YearPickerView(Context context, AttributeSet attrs) {
|
|
this(context, attrs, R.attr.listViewStyle);
|
|
}
|
|
|
|
public YearPickerView(Context context, AttributeSet attrs, int defStyleAttr) {
|
|
this(context, attrs, defStyleAttr, 0);
|
|
}
|
|
|
|
public YearPickerView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
|
|
super(context, attrs, defStyleAttr, defStyleRes);
|
|
|
|
final LayoutParams frame = new LayoutParams(
|
|
LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT);
|
|
setLayoutParams(frame);
|
|
|
|
final Resources res = context.getResources();
|
|
mViewSize = res.getDimensionPixelOffset(R.dimen.datepicker_view_animator_height);
|
|
mChildSize = res.getDimensionPixelOffset(R.dimen.datepicker_year_label_height);
|
|
|
|
setOnItemClickListener(new OnItemClickListener() {
|
|
@Override
|
|
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
|
|
final int year = mAdapter.getYearForPosition(position);
|
|
mAdapter.setSelection(year);
|
|
|
|
if (mOnYearSelectedListener != null) {
|
|
mOnYearSelectedListener.onYearChanged(YearPickerView.this, year);
|
|
}
|
|
}
|
|
});
|
|
|
|
mAdapter = new YearAdapter(getContext());
|
|
setAdapter(mAdapter);
|
|
}
|
|
|
|
public void setOnYearSelectedListener(OnYearSelectedListener listener) {
|
|
mOnYearSelectedListener = listener;
|
|
}
|
|
|
|
/**
|
|
* Sets the currently selected year. Jumps immediately to the new year.
|
|
*
|
|
* @param year the target year
|
|
*/
|
|
public void setYear(final int year) {
|
|
mAdapter.setSelection(year);
|
|
|
|
post(new Runnable() {
|
|
@Override
|
|
public void run() {
|
|
final int position = mAdapter.getPositionForYear(year);
|
|
if (position >= 0 && position < getCount()) {
|
|
setSelectionCentered(position);
|
|
}
|
|
}
|
|
});
|
|
}
|
|
|
|
public void setSelectionCentered(int position) {
|
|
final int offset = mViewSize / 2 - mChildSize / 2;
|
|
setSelectionFromTop(position, offset);
|
|
}
|
|
|
|
public void setRange(Calendar min, Calendar max) {
|
|
mAdapter.setRange(min, max);
|
|
}
|
|
|
|
private static class YearAdapter extends BaseAdapter {
|
|
private static final int ITEM_LAYOUT = R.layout.year_label_text_view;
|
|
private static final int ITEM_TEXT_APPEARANCE =
|
|
R.style.TextAppearance_Material_DatePicker_List_YearLabel;
|
|
private static final int ITEM_TEXT_ACTIVATED_APPEARANCE =
|
|
R.style.TextAppearance_Material_DatePicker_List_YearLabel_Activated;
|
|
|
|
private final LayoutInflater mInflater;
|
|
|
|
private int mActivatedYear;
|
|
private int mMinYear;
|
|
private int mCount;
|
|
|
|
public YearAdapter(Context context) {
|
|
mInflater = LayoutInflater.from(context);
|
|
}
|
|
|
|
public void setRange(Calendar minDate, Calendar maxDate) {
|
|
final int minYear = minDate.get(Calendar.YEAR);
|
|
final int count = maxDate.get(Calendar.YEAR) - minYear + 1;
|
|
|
|
if (mMinYear != minYear || mCount != count) {
|
|
mMinYear = minYear;
|
|
mCount = count;
|
|
notifyDataSetInvalidated();
|
|
}
|
|
}
|
|
|
|
public boolean setSelection(int year) {
|
|
if (mActivatedYear != year) {
|
|
mActivatedYear = year;
|
|
notifyDataSetChanged();
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
@Override
|
|
public int getCount() {
|
|
return mCount;
|
|
}
|
|
|
|
@Override
|
|
public Integer getItem(int position) {
|
|
return getYearForPosition(position);
|
|
}
|
|
|
|
@Override
|
|
public long getItemId(int position) {
|
|
return getYearForPosition(position);
|
|
}
|
|
|
|
public int getPositionForYear(int year) {
|
|
return year - mMinYear;
|
|
}
|
|
|
|
public int getYearForPosition(int position) {
|
|
return mMinYear + position;
|
|
}
|
|
|
|
@Override
|
|
public boolean hasStableIds() {
|
|
return true;
|
|
}
|
|
|
|
@Override
|
|
public View getView(int position, View convertView, ViewGroup parent) {
|
|
final TextView v;
|
|
final boolean hasNewView = convertView == null;
|
|
if (hasNewView) {
|
|
v = (TextView) mInflater.inflate(ITEM_LAYOUT, parent, false);
|
|
} else {
|
|
v = (TextView) convertView;
|
|
}
|
|
|
|
final int year = getYearForPosition(position);
|
|
final boolean activated = mActivatedYear == year;
|
|
|
|
if (hasNewView || v.isActivated() != activated) {
|
|
final int textAppearanceResId;
|
|
if (activated && ITEM_TEXT_ACTIVATED_APPEARANCE != 0) {
|
|
textAppearanceResId = ITEM_TEXT_ACTIVATED_APPEARANCE;
|
|
} else {
|
|
textAppearanceResId = ITEM_TEXT_APPEARANCE;
|
|
}
|
|
v.setTextAppearance(textAppearanceResId);
|
|
v.setActivated(activated);
|
|
}
|
|
|
|
v.setText(Integer.toString(year));
|
|
return v;
|
|
}
|
|
|
|
@Override
|
|
public int getItemViewType(int position) {
|
|
return 0;
|
|
}
|
|
|
|
@Override
|
|
public int getViewTypeCount() {
|
|
return 1;
|
|
}
|
|
|
|
@Override
|
|
public boolean isEmpty() {
|
|
return false;
|
|
}
|
|
|
|
@Override
|
|
public boolean areAllItemsEnabled() {
|
|
return true;
|
|
}
|
|
|
|
@Override
|
|
public boolean isEnabled(int position) {
|
|
return true;
|
|
}
|
|
}
|
|
|
|
public int getFirstPositionOffset() {
|
|
final View firstChild = getChildAt(0);
|
|
if (firstChild == null) {
|
|
return 0;
|
|
}
|
|
return firstChild.getTop();
|
|
}
|
|
|
|
/** @hide */
|
|
@Override
|
|
public void onInitializeAccessibilityEventInternal(AccessibilityEvent event) {
|
|
super.onInitializeAccessibilityEventInternal(event);
|
|
|
|
// There are a bunch of years, so don't bother.
|
|
if (event.getEventType() == AccessibilityEvent.TYPE_VIEW_SCROLLED) {
|
|
event.setFromIndex(0);
|
|
event.setToIndex(0);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* The callback used to indicate the user changed the year.
|
|
*/
|
|
public interface OnYearSelectedListener {
|
|
/**
|
|
* Called upon a year change.
|
|
*
|
|
* @param view The view associated with this listener.
|
|
* @param year The year that was set.
|
|
*/
|
|
void onYearChanged(YearPickerView view, int year);
|
|
}
|
|
} |