/*
* 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 com.tr4android.support.extension.picker.date;
import android.content.Context;
import android.content.res.Resources;
import android.support.v4.view.accessibility.AccessibilityEventCompat;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.accessibility.AccessibilityEvent;
import android.widget.TextView;
import com.tr4android.appcompat.extension.R;
import com.tr4android.support.extension.utils.ViewCompatUtils;
import java.util.Calendar;
/**
* Displays a selectable list of years.
*/
class YearPickerView extends RecyclerView implements View.OnClickListener {
private final YearAdapter mAdapter;
private final int mChildSize;
private OnYearSelectedListener mOnYearSelectedListener;
private long mCurrentTimeMillis;
public YearPickerView(Context context, AttributeSet attrs) {
this(context, attrs, 0); //TODO: look into R.attr.listViewStyle
}
public YearPickerView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
final LayoutParams frame = new LayoutParams(
LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT);
setLayoutParams(frame);
final Resources res = context.getResources();
mChildSize = res.getDimensionPixelOffset(R.dimen.datepicker_year_label_height);
setLayoutManager(new LinearLayoutManager(getContext()));
mAdapter = new YearAdapter(getContext(), this);
setAdapter(mAdapter);
}
@Override
public void onClick(View view) {
final int position = getChildAdapterPosition(view);
if (position == -1) return; // Ignore invalid positions
final int year = mAdapter.getYearForPosition(position);
mAdapter.setSelection(year);
if (mOnYearSelectedListener != null) {
mOnYearSelectedListener.onYearChanged(YearPickerView.this, year);
}
}
public void setOnYearSelectedListener(OnYearSelectedListener listener) {
mOnYearSelectedListener = listener;
}
public void setDate(long currentTimeMillis) {
mCurrentTimeMillis = currentTimeMillis;
}
/**
* 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 < mAdapter.getItemCount()) {
setSelectionCentered(position);
}
}
});
}
public void setSelectionCentered(int position) {
final int offset = getMeasuredHeight() / 2 - mChildSize / 2;
setSelectionFromTop(position, offset);
}
public void setRange(Calendar min, Calendar max) {
mAdapter.setRange(min, max);
}
private static class YearAdapter extends RecyclerView.Adapter<YearAdapter.ViewHolder> {
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_SELECTED_APPEARANCE =
R.style.TextAppearance_Material_DatePicker_List_YearLabel_Selected;
private static final int ITEM_IS_SELECTED = R.id.date_picker_year_item_is_selected;
private final LayoutInflater mInflater;
private final OnClickListener mListener;
public static class ViewHolder extends RecyclerView.ViewHolder{
public TextView mYearView;
public ViewHolder(View itemView) {
super(itemView);
mYearView = (TextView) itemView;
}
}
private int mSelectedYear;
private int mMinYear;
private int mCount;
public YearAdapter(Context context, OnClickListener listener) {
mInflater = LayoutInflater.from(context);
mListener = listener;
}
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;
notifyDataSetChanged();
}
}
public boolean setSelection(int year) {
if (mSelectedYear != year) {
mSelectedYear = year;
notifyDataSetChanged();
return true;
}
return false;
}
@Override
public int getItemCount() {
return mCount;
}
@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 ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
return new ViewHolder(mInflater.inflate(ITEM_LAYOUT, parent, false));
}
@Override
public void onBindViewHolder(ViewHolder holder, int position) {
final int year = getYearForPosition(position);
final boolean selected = mSelectedYear == year;
Object tag = holder.mYearView.getTag(ITEM_IS_SELECTED);
if (tag == null || (boolean) tag != selected) {
final int textAppearanceResId;
if (selected && ITEM_TEXT_SELECTED_APPEARANCE != 0) {
textAppearanceResId = ITEM_TEXT_SELECTED_APPEARANCE;
} else {
textAppearanceResId = ITEM_TEXT_APPEARANCE;
}
ViewCompatUtils.setTextAppearance(holder.mYearView, textAppearanceResId);
holder.mYearView.setTag(ITEM_IS_SELECTED, selected);
}
holder.mYearView.setText(Integer.toString(year));
holder.mYearView.setOnClickListener(mListener);
}
}
public void setSelectionFromTop(int position, int offset) {
((LinearLayoutManager) getLayoutManager()).scrollToPositionWithOffset(position, offset);
}
public int getFirstVisiblePosition() {
return ((LinearLayoutManager) getLayoutManager()).findFirstVisibleItemPosition();
}
public int getFirstPositionOffset() {
final View firstChild = getChildAt(0);
if (firstChild == null) {
return 0;
}
return firstChild.getTop();
}
/** @hide */
@Override
public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
super.onInitializeAccessibilityEvent(event);
// There are a bunch of years, so don't bother.
if (event.getEventType() == AccessibilityEvent.TYPE_VIEW_SCROLLED) {
AccessibilityEventCompat.asRecord(event).setFromIndex(0);
AccessibilityEventCompat.asRecord(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);
}
}