diff options
author | Romain Guy <romainguy@google.com> | 2012-04-03 20:22:10 -0700 |
---|---|---|
committer | Romain Guy <romainguy@google.com> | 2012-04-03 21:15:12 -0700 |
commit | 2946445b560fde5e63df17f5a2db60c8349fe532 (patch) | |
tree | 151f9c409903b291045664b6dd91298f88443fd0 /tests/HwAccelerationTest | |
parent | e0aa84b7dc087e999e20055dcc04cb6a48d5bd62 (diff) | |
download | frameworks_base-2946445b560fde5e63df17f5a2db60c8349fe532.zip frameworks_base-2946445b560fde5e63df17f5a2db60c8349fe532.tar.gz frameworks_base-2946445b560fde5e63df17f5a2db60c8349fe532.tar.bz2 |
New libhwui test activity
Change-Id: I0ce4bc665f117d7c0ed47670ceb4ed6f9b54d85c
Diffstat (limited to 'tests/HwAccelerationTest')
4 files changed, 604 insertions, 0 deletions
diff --git a/tests/HwAccelerationTest/AndroidManifest.xml b/tests/HwAccelerationTest/AndroidManifest.xml index b310d93..3a2fe43 100644 --- a/tests/HwAccelerationTest/AndroidManifest.xml +++ b/tests/HwAccelerationTest/AndroidManifest.xml @@ -42,6 +42,15 @@ </activity> <activity + android:name="DatePickerActivity" + android:label="_DatePicker"> + <intent-filter> + <action android:name="android.intent.action.MAIN" /> + <category android:name="android.intent.category.LAUNCHER" /> + </intent-filter> + </activity> + + <activity android:name="ClipRegionActivity" android:label="_ClipRegion"> <intent-filter> diff --git a/tests/HwAccelerationTest/res/layout/date_picker.xml b/tests/HwAccelerationTest/res/layout/date_picker.xml new file mode 100644 index 0000000..742a03b --- /dev/null +++ b/tests/HwAccelerationTest/res/layout/date_picker.xml @@ -0,0 +1,83 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +** +** Copyright 2012, 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. +*/ +--> + +<!-- Layout of date picker--> + +<!-- The width of this container is manually set a little bigger than the one of the children + contained in it. This helps to prevent rounding errors when toggling the "Show year" option --> + +<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" + android:orientation="vertical" + android:layout_gravity="center_horizontal" + android:layout_width="270dip" + android:layout_height="wrap_content"> + + <CheckBox + android:id="@+id/yearToggle" + android:text="Provide a year" + android:paddingTop="5dip" + android:paddingBottom="5dip" + android:textAppearance="?android:attr/textAppearanceLarge" + android:layout_gravity="center_horizontal" + android:layout_width="wrap_content" + android:layout_height="wrap_content"/> + <!-- Warning: everything within the parent is removed and re-ordered depending + on the date format selected by the user. --> + <LinearLayout + android:id="@+id/parent" + android:orientation="horizontal" + android:layout_gravity="center_horizontal" + android:animateLayoutChanges="true" + android:layout_width="wrap_content" + android:layout_height="wrap_content"> + + <!-- Month --> + <NumberPicker + android:id="@+id/month" + android:layout_width="80dip" + android:layout_height="wrap_content" + android:layout_marginLeft="1dip" + android:layout_marginRight="1dip" + android:focusable="true" + android:focusableInTouchMode="true" + /> + + <!-- Day --> + <NumberPicker + android:id="@+id/day" + android:layout_width="80dip" + android:layout_height="wrap_content" + android:layout_marginLeft="1dip" + android:layout_marginRight="1dip" + android:focusable="true" + android:focusableInTouchMode="true" + /> + + <!-- Year --> + <NumberPicker + android:id="@+id/year" + android:layout_width="95dip" + android:layout_height="wrap_content" + android:layout_marginLeft="1dip" + android:layout_marginRight="1dip" + android:focusable="true" + android:focusableInTouchMode="true" + /> + </LinearLayout> +</LinearLayout> diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/DatePicker.java b/tests/HwAccelerationTest/src/com/android/test/hwui/DatePicker.java new file mode 100644 index 0000000..db247e3 --- /dev/null +++ b/tests/HwAccelerationTest/src/com/android/test/hwui/DatePicker.java @@ -0,0 +1,474 @@ +/* + * Copyright (C) 2012 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.android.test.hwui; + +import android.annotation.Widget; +import android.content.Context; +import android.content.res.TypedArray; +import android.os.Parcel; +import android.os.Parcelable; +import android.text.format.DateFormat; +import android.util.AttributeSet; +import android.util.SparseArray; +import android.view.ContextThemeWrapper; +import android.view.LayoutInflater; +import android.view.View; +import android.widget.CheckBox; +import android.widget.CompoundButton; +import android.widget.FrameLayout; +import android.widget.LinearLayout; +import android.widget.NumberPicker; + +import java.text.DateFormatSymbols; +import java.text.SimpleDateFormat; +import java.util.Calendar; + +/** + * A view for selecting a month / year / day based on a calendar like layout. + * + * <p>See the <a href="{@docRoot}resources/tutorials/views/hello-datepicker.html">Date Picker + * tutorial</a>.</p> + * + * For a dialog using this view, see {@link android.app.DatePickerDialog}. + */ +@Widget +public class DatePicker extends FrameLayout { + + private static final int DEFAULT_START_YEAR = 1900; + private static final int DEFAULT_END_YEAR = 2100; + + /* UI Components */ + private final CheckBox mYearToggle; + private final NumberPicker mDayPicker; + private final NumberPicker mMonthPicker; + private final NumberPicker mYearPicker; + + /** + * How we notify users the date has changed. + */ + private OnDateChangedListener mOnDateChangedListener; + + private int mDay; + private int mMonth; + private int mYear; + private boolean mYearOptional = true; + private boolean mHasYear; + + /** + * The callback used to indicate the user changes the date. + */ + public interface OnDateChangedListener { + + /** + * @param view The view associated with this listener. + * @param year The year that was set. + * @param monthOfYear The month that was set (0-11) for compatibility + * with {@link java.util.Calendar}. + * @param dayOfMonth The day of the month that was set. + */ + void onDateChanged(DatePicker view, int year, int monthOfYear, int dayOfMonth); + } + + public DatePicker(Context context) { + this(context, null); + } + + public DatePicker(Context context, AttributeSet attrs) { + this(context, attrs, 0); + } + + @SuppressWarnings("deprecation") + public DatePicker(Context context, AttributeSet attrs, int defStyle) { + super(context, attrs, defStyle); + + ContextThemeWrapper themed = new ContextThemeWrapper(context, + com.android.internal.R.style.Theme_Holo_Light_Dialog_Alert); + LayoutInflater inflater = (LayoutInflater) themed.getSystemService( + Context.LAYOUT_INFLATER_SERVICE); + inflater.inflate(R.layout.date_picker, this, true); + + mDayPicker = (NumberPicker) findViewById(R.id.day); + mDayPicker.setFormatter(NumberPicker.TWO_DIGIT_FORMATTER); + mDayPicker.setOnLongPressUpdateInterval(100); + mDayPicker.setOnValueChangedListener(new NumberPicker.OnValueChangeListener() { + public void onValueChange(NumberPicker picker, int oldVal, int newVal) { + mDay = newVal; + notifyDateChanged(); + } + }); + mMonthPicker = (NumberPicker) findViewById(R.id.month); + mMonthPicker.setFormatter(NumberPicker.TWO_DIGIT_FORMATTER); + DateFormatSymbols dfs = new DateFormatSymbols(); + String[] months = dfs.getShortMonths(); + + /* + * If the user is in a locale where the month names are numeric, + * use just the number instead of the "month" character for + * consistency with the other fields. + */ + if (months[0].startsWith("1")) { + for (int i = 0; i < months.length; i++) { + months[i] = String.valueOf(i + 1); + } + mMonthPicker.setMinValue(1); + mMonthPicker.setMaxValue(12); + } else { + mMonthPicker.setMinValue(1); + mMonthPicker.setMaxValue(12); + mMonthPicker.setDisplayedValues(months); + } + + mMonthPicker.setOnLongPressUpdateInterval(200); + mMonthPicker.setOnValueChangedListener(new NumberPicker.OnValueChangeListener() { + public void onValueChange(NumberPicker picker, int oldVal, int newVal) { + + /* We display the month 1-12 but store it 0-11 so always + * subtract by one to ensure our internal state is always 0-11 + */ + mMonth = newVal - 1; + // Adjust max day of the month + adjustMaxDay(); + notifyDateChanged(); + updateDaySpinner(); + } + }); + mYearPicker = (NumberPicker) findViewById(R.id.year); + mYearPicker.setOnLongPressUpdateInterval(100); + mYearPicker.setOnValueChangedListener(new NumberPicker.OnValueChangeListener() { + public void onValueChange(NumberPicker picker, int oldVal, int newVal) { + mYear = newVal; + // Adjust max day for leap years if needed + adjustMaxDay(); + notifyDateChanged(); + updateDaySpinner(); + } + }); + + mYearToggle = (CheckBox) findViewById(R.id.yearToggle); + mYearToggle.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { + @Override + public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { + mHasYear = isChecked; + adjustMaxDay(); + notifyDateChanged(); + updateSpinners(); + } + }); + + // attributes + TypedArray a = context.obtainStyledAttributes(attrs, + com.android.internal.R.styleable.DatePicker); + + int mStartYear = + a.getInt(com.android.internal.R.styleable.DatePicker_startYear, DEFAULT_START_YEAR); + int mEndYear = + a.getInt(com.android.internal.R.styleable.DatePicker_endYear, DEFAULT_END_YEAR); + mYearPicker.setMinValue(mStartYear); + mYearPicker.setMaxValue(mEndYear); + + a.recycle(); + + // initialize to current date + Calendar cal = Calendar.getInstance(); + init(cal.get(Calendar.YEAR), cal.get(Calendar.MONTH), cal.get(Calendar.DAY_OF_MONTH), null); + + // re-order the number pickers to match the current date format + reorderPickers(months); + + if (!isEnabled()) { + setEnabled(false); + } + } + + @Override + public void setEnabled(boolean enabled) { + super.setEnabled(enabled); + mDayPicker.setEnabled(enabled); + mMonthPicker.setEnabled(enabled); + mYearPicker.setEnabled(enabled); + } + + private void reorderPickers(String[] months) { + java.text.DateFormat format; + String order; + + /* + * If the user is in a locale where the medium date format is + * still numeric (Japanese and Czech, for example), respect + * the date format order setting. Otherwise, use the order + * that the locale says is appropriate for a spelled-out date. + */ + + if (months[0].startsWith("1")) { + format = DateFormat.getDateFormat(getContext()); + } else { + format = DateFormat.getMediumDateFormat(getContext()); + } + + if (format instanceof SimpleDateFormat) { + order = ((SimpleDateFormat) format).toPattern(); + } else { + // Shouldn't happen, but just in case. + order = new String(DateFormat.getDateFormatOrder(getContext())); + } + + /* Remove the 3 pickers from their parent and then add them back in the + * required order. + */ + LinearLayout parent = (LinearLayout) findViewById(R.id.parent); + parent.removeAllViews(); + + boolean quoted = false; + boolean didDay = false, didMonth = false, didYear = false; + + for (int i = 0; i < order.length(); i++) { + char c = order.charAt(i); + + if (c == '\'') { + quoted = !quoted; + } + + if (!quoted) { + if (c == DateFormat.DATE && !didDay) { + parent.addView(mDayPicker); + didDay = true; + } else if ((c == DateFormat.MONTH || c == 'L') && !didMonth) { + parent.addView(mMonthPicker); + didMonth = true; + } else if (c == DateFormat.YEAR && !didYear) { + parent.addView (mYearPicker); + didYear = true; + } + } + } + + // Shouldn't happen, but just in case. + if (!didMonth) { + parent.addView(mMonthPicker); + } + if (!didDay) { + parent.addView(mDayPicker); + } + if (!didYear) { + parent.addView(mYearPicker); + } + } + + public void updateDate(int year, int monthOfYear, int dayOfMonth) { + if (mYear != year || mMonth != monthOfYear || mDay != dayOfMonth) { + mYear = (mYearOptional && year == 0) ? getCurrentYear() : year; + mMonth = monthOfYear; + mDay = dayOfMonth; + updateSpinners(); + reorderPickers(new DateFormatSymbols().getShortMonths()); + notifyDateChanged(); + } + } + + private static int getCurrentYear() { + return Calendar.getInstance().get(Calendar.YEAR); + } + + private static class SavedState extends BaseSavedState { + + private final int mYear; + private final int mMonth; + private final int mDay; + private final boolean mHasYear; + private final boolean mYearOptional; + + /** + * Constructor called from {@link DatePicker#onSaveInstanceState()} + */ + private SavedState(Parcelable superState, int year, int month, int day, boolean hasYear, + boolean yearOptional) { + super(superState); + mYear = year; + mMonth = month; + mDay = day; + mHasYear = hasYear; + mYearOptional = yearOptional; + } + + /** + * Constructor called from {@link #CREATOR} + */ + private SavedState(Parcel in) { + super(in); + mYear = in.readInt(); + mMonth = in.readInt(); + mDay = in.readInt(); + mHasYear = in.readInt() != 0; + mYearOptional = in.readInt() != 0; + } + + public int getYear() { + return mYear; + } + + public int getMonth() { + return mMonth; + } + + public int getDay() { + return mDay; + } + + public boolean hasYear() { + return mHasYear; + } + + public boolean isYearOptional() { + return mYearOptional; + } + + @Override + public void writeToParcel(Parcel dest, int flags) { + super.writeToParcel(dest, flags); + dest.writeInt(mYear); + dest.writeInt(mMonth); + dest.writeInt(mDay); + dest.writeInt(mHasYear ? 1 : 0); + dest.writeInt(mYearOptional ? 1 : 0); + } + + @SuppressWarnings("unused") + public static final Parcelable.Creator<SavedState> CREATOR = + new Creator<SavedState>() { + + public SavedState createFromParcel(Parcel in) { + return new SavedState(in); + } + + public SavedState[] newArray(int size) { + return new SavedState[size]; + } + }; + } + + + /** + * Override so we are in complete control of save / restore for this widget. + */ + @Override + protected void dispatchRestoreInstanceState(SparseArray<Parcelable> container) { + dispatchThawSelfOnly(container); + } + + @Override + protected Parcelable onSaveInstanceState() { + Parcelable superState = super.onSaveInstanceState(); + + return new SavedState(superState, mYear, mMonth, mDay, mHasYear, mYearOptional); + } + + @Override + protected void onRestoreInstanceState(Parcelable state) { + SavedState ss = (SavedState) state; + super.onRestoreInstanceState(ss.getSuperState()); + mYear = ss.getYear(); + mMonth = ss.getMonth(); + mDay = ss.getDay(); + mHasYear = ss.hasYear(); + mYearOptional = ss.isYearOptional(); + updateSpinners(); + } + + /** + * Initialize the state. + * @param year The initial year. + * @param monthOfYear The initial month. + * @param dayOfMonth The initial day of the month. + * @param onDateChangedListener How user is notified date is changed by user, can be null. + */ + public void init(int year, int monthOfYear, int dayOfMonth, + OnDateChangedListener onDateChangedListener) { + init(year, monthOfYear, dayOfMonth, false, onDateChangedListener); + } + + /** + * Initialize the state. + * @param year The initial year or 0 if no year has been specified + * @param monthOfYear The initial month. + * @param dayOfMonth The initial day of the month. + * @param yearOptional True if the user can toggle the year + * @param onDateChangedListener How user is notified date is changed by user, can be null. + */ + public void init(int year, int monthOfYear, int dayOfMonth, boolean yearOptional, + OnDateChangedListener onDateChangedListener) { + mYear = (yearOptional && year == 0) ? getCurrentYear() : year; + mMonth = monthOfYear; + mDay = dayOfMonth; + mYearOptional = yearOptional; + mHasYear = !yearOptional || (year != 0); + mOnDateChangedListener = onDateChangedListener; + updateSpinners(); + } + + private void updateSpinners() { + updateDaySpinner(); + mYearToggle.setChecked(mHasYear); + mYearToggle.setVisibility(mYearOptional ? View.VISIBLE : View.GONE); + mYearPicker.setValue(mYear); + mYearPicker.setVisibility(mHasYear ? View.VISIBLE : View.GONE); + + /* The month display uses 1-12 but our internal state stores it + * 0-11 so add one when setting the display. + */ + mMonthPicker.setValue(mMonth + 1); + } + + private void updateDaySpinner() { + Calendar cal = Calendar.getInstance(); + // if year was not set, use 2000 as it was a leap year + cal.set(mHasYear ? mYear : 2000, mMonth, 1); + int max = cal.getActualMaximum(Calendar.DAY_OF_MONTH); + mDayPicker.setMinValue(1); + mDayPicker.setMaxValue(max); + mDayPicker.setValue(mDay); + } + + public int getYear() { + return (mYearOptional && !mHasYear) ? 0 : mYear; + } + + public int getMonth() { + return mMonth; + } + + public int getDayOfMonth() { + return mDay; + } + + private void adjustMaxDay(){ + Calendar cal = Calendar.getInstance(); + // if year was not set, use 2000 as it was a leap year + cal.set(Calendar.YEAR, mHasYear ? mYear : 2000); + cal.set(Calendar.MONTH, mMonth); + int max = cal.getActualMaximum(Calendar.DAY_OF_MONTH); + if (mDay > max) { + mDay = max; + } + } + + private void notifyDateChanged() { + if (mOnDateChangedListener != null) { + int year = (mYearOptional && !mHasYear) ? 0 : mYear; + mOnDateChangedListener.onDateChanged(DatePicker.this, year, mMonth, mDay); + } + } +} diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/DatePickerActivity.java b/tests/HwAccelerationTest/src/com/android/test/hwui/DatePickerActivity.java new file mode 100644 index 0000000..5482ee2 --- /dev/null +++ b/tests/HwAccelerationTest/src/com/android/test/hwui/DatePickerActivity.java @@ -0,0 +1,38 @@ +/* + * Copyright (C) 2010 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.android.test.hwui; + +import android.app.Activity; +import android.graphics.drawable.ColorDrawable; +import android.os.Bundle; + +@SuppressWarnings({"UnusedDeclaration"}) +public class DatePickerActivity extends Activity { + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + DatePicker picker = new DatePicker(this); + picker.init(2012, 3, 3, true, new DatePicker.OnDateChangedListener() { + @Override + public void onDateChanged(DatePicker view, int year, int monthOfYear, int dayOfMonth) { + } + }); + setContentView(picker); + getWindow().setBackgroundDrawable(new ColorDrawable(0xffffffff)); + } +} |