Add browseable samples for Clockwork Beryl

Bug: 17473824
Change-Id: Id4c637733c491ac71bb6e269f55939c082fb0994
This commit is contained in:
Trevor Johns
2014-10-22 20:10:29 -07:00
parent 4a5ce9aedf
commit f420ff0d80
797 changed files with 34843 additions and 0 deletions

View File

@@ -0,0 +1,138 @@
/*
* 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.example.android.notifications;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.ObjectAnimator;
import android.animation.PropertyValuesHolder;
import android.app.Activity;
import android.content.Context;
import android.os.Bundle;
import android.view.ViewGroup;
import android.view.animation.AccelerateDecelerateInterpolator;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.TextView;
import java.util.Random;
/**
* Custom display activity for an animated sample notification.
*/
public class AnimatedNotificationDisplayActivity extends Activity {
public static final String EXTRA_TITLE = "title";
private static final int BASE_ANIMATION_DURATION_MS = 2000;
private Random mRandom;
private int mAnimationRange;
private ImageView mImageView;
private Animator mAnimation;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_animated_notification_display);
mRandom = new Random(System.currentTimeMillis());
mAnimationRange = getResources().getDimensionPixelSize(R.dimen.animation_range);
String title = getIntent().getStringExtra(EXTRA_TITLE);
((TextView) findViewById(R.id.title)).setText(title);
mImageView = new ImageView(this);
mImageView.setImageResource(R.drawable.example_big_picture);
ImageZoomView zoomView = new ImageZoomView(this, mImageView, mAnimationRange);
zoomView.setLayoutParams(new FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.MATCH_PARENT));
((FrameLayout) findViewById(R.id.container)).addView(zoomView, 0);
createNextAnimation(false);
}
private void createNextAnimation(boolean start) {
float startX = mImageView.getTranslationX();
float startY = mImageView.getTranslationY();
float endX = -mRandom.nextInt(mAnimationRange);
float endY = -mRandom.nextInt(mAnimationRange);
float distance = (float) Math.sqrt(Math.pow(endX - startX, 2) + Math.pow(endY - startY, 2));
mAnimation = ObjectAnimator.ofPropertyValuesHolder(mImageView,
PropertyValuesHolder.ofFloat("translationX", startX, endX),
PropertyValuesHolder.ofFloat("translationY", startY, endY));
mAnimation.setInterpolator(new AccelerateDecelerateInterpolator());
mAnimation.setDuration(Math.max(BASE_ANIMATION_DURATION_MS / 10,
(int) (distance * BASE_ANIMATION_DURATION_MS / mAnimationRange)));
mAnimation.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
super.onAnimationEnd(animation);
createNextAnimation(true);
}
});
if (start) {
mAnimation.start();
}
}
@Override
protected void onResume() {
super.onResume();
mAnimation.start();
}
@Override
protected void onPause() {
mAnimation.pause();
super.onPause();
}
/** Helper view that zooms in on a child image view */
private static class ImageZoomView extends ViewGroup {
private final int mZoomLength;
public ImageZoomView(Context context, ImageView imageView, int zoomLength) {
super(context);
addView(imageView);
mZoomLength = zoomLength;
}
@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
ImageView imageView = (ImageView) getChildAt(0);
// Resize the image view to be at least mZoomLength pixels larger in both
// dimensions than the containing view.
int imageWidth = imageView.getDrawable().getIntrinsicWidth();
int imageHeight = imageView.getDrawable().getIntrinsicHeight();
int minSize = Math.max(right - left, bottom - top) + mZoomLength;
if (imageWidth > imageHeight) {
imageWidth = minSize * imageWidth / imageHeight;
imageHeight = minSize;
} else {
imageHeight = minSize * imageHeight / imageWidth;
imageWidth = minSize;
}
imageView.layout(left, top, left + imageWidth, top + imageHeight);
}
}
}

View File

@@ -0,0 +1,38 @@
/*
* 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.example.android.notifications;
import android.app.Activity;
import android.os.Bundle;
import android.widget.TextView;
/**
* Custom display activity for a sample notification.
*/
public class BasicNotificationDisplayActivity extends Activity {
public static final String EXTRA_TITLE = "title";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_notification_display);
String title = getIntent().getStringExtra(EXTRA_TITLE);
((TextView) findViewById(R.id.title)).setText(title);
}
}

View File

@@ -0,0 +1,106 @@
/*
* 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.example.android.notifications;
import android.app.Activity;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.RemoteInput;
import android.content.Context;
import android.os.Bundle;
import android.support.wearable.view.WearableListView;
import android.text.TextUtils;
import android.view.LayoutInflater;
import android.view.ViewGroup;
import android.widget.TextView;
import android.widget.Toast;
public class MainActivity extends Activity implements WearableListView.ClickListener {
private static final int SAMPLE_NOTIFICATION_ID = 0;
public static final String KEY_REPLY = "reply";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
WearableListView listView = (WearableListView) findViewById(R.id.list);
listView.setAdapter(new Adapter(this));
listView.setClickListener(this);
}
@Override
protected void onResume() {
super.onResume();
if (getIntent() != null) {
Bundle inputResults = RemoteInput.getResultsFromIntent(getIntent());
if (inputResults != null) {
CharSequence replyText = inputResults.getCharSequence(KEY_REPLY);
if (replyText != null) {
Toast.makeText(this, TextUtils.concat(getString(R.string.reply_was), replyText),
Toast.LENGTH_LONG).show();
}
}
}
}
/** Post a new or updated notification using the selected notification options. */
private void updateNotification(int presetIndex) {
NotificationPreset preset = NotificationPresets.PRESETS[presetIndex];
Notification notif = preset.buildNotification(this);
((NotificationManager) getSystemService(NOTIFICATION_SERVICE))
.notify(SAMPLE_NOTIFICATION_ID, notif);
finish();
}
@Override
public void onClick(WearableListView.ViewHolder v) {
updateNotification((Integer) v.itemView.getTag());
}
@Override
public void onTopEmptyRegionClick() {
}
private static final class Adapter extends WearableListView.Adapter {
private final Context mContext;
private final LayoutInflater mInflater;
private Adapter(Context context) {
mContext = context;
mInflater = LayoutInflater.from(context);
}
@Override
public WearableListView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
return new WearableListView.ViewHolder(
mInflater.inflate(R.layout.notif_preset_list_item, null));
}
@Override
public void onBindViewHolder(WearableListView.ViewHolder holder, int position) {
TextView view = (TextView) holder.itemView.findViewById(R.id.name);
view.setText(mContext.getString(NotificationPresets.PRESETS[position].nameResId));
holder.itemView.setTag(position);
}
@Override
public int getItemCount() {
return NotificationPresets.PRESETS.length;
}
}
}

View File

@@ -0,0 +1,34 @@
/*
* 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.example.android.notifications;
import android.app.Notification;
import android.content.Context;
/**
* Base class for notification preset generators.
*/
public abstract class NotificationPreset {
public final int nameResId;
public NotificationPreset(int nameResId) {
this.nameResId = nameResId;
}
/** Start building a notification with this preset */
public abstract Notification buildNotification(Context context);
}

View File

@@ -0,0 +1,314 @@
/*
* 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.example.android.notifications;
import android.app.Notification;
import android.app.PendingIntent;
import android.app.RemoteInput;
import android.content.Context;
import android.content.Intent;
import android.graphics.BitmapFactory;
import android.graphics.Color;
import android.graphics.Typeface;
import android.net.Uri;
import android.text.SpannableStringBuilder;
import android.text.style.ForegroundColorSpan;
import android.text.style.RelativeSizeSpan;
import android.text.style.StrikethroughSpan;
import android.text.style.StyleSpan;
import android.text.style.SubscriptSpan;
import android.text.style.SuperscriptSpan;
import android.text.style.TypefaceSpan;
import android.text.style.UnderlineSpan;
import android.util.TypedValue;
import android.view.Gravity;
/**
* Collection of notification builder presets.
*/
public class NotificationPresets {
public static final NotificationPreset[] PRESETS = new NotificationPreset[] {
new BasicPreset(),
new StylizedTextPreset(),
new DisplayIntentPreset(),
new MultiSizeDisplayIntentPreset(),
new AnimatedDisplayIntentPreset(),
new ContentIconPreset()
};
private static Notification.Builder buildBasicNotification(Context context) {
return new Notification.Builder(context)
.setContentTitle(context.getString(R.string.example_content_title))
.setContentText(context.getString(R.string.example_content_text))
// Set a content intent to return to this sample
.setContentIntent(PendingIntent.getActivity(context, 0,
new Intent(context, MainActivity.class), 0))
.setSmallIcon(R.mipmap.ic_launcher);
}
private static class BasicPreset extends NotificationPreset {
public BasicPreset() {
super(R.string.basic_example);
}
@Override
public Notification buildNotification(Context context) {
PendingIntent pendingIntent = PendingIntent.getActivity(context, 0,
new Intent(context, MainActivity.class), 0);
Notification page2 = buildBasicNotification(context)
.extend(new Notification.WearableExtender()
.setHintShowBackgroundOnly(true)
.setBackground(BitmapFactory.decodeResource(context.getResources(),
R.drawable.example_big_picture)))
.build();
Notification page3 = buildBasicNotification(context)
.setContentTitle(context.getString(R.string.third_page))
.setContentText(null)
.extend(new Notification.WearableExtender()
.setContentAction(0 /* action A */))
.build();
SpannableStringBuilder choice2 = new SpannableStringBuilder(
"This choice is best");
choice2.setSpan(new StyleSpan(Typeface.BOLD_ITALIC), 5, 11, 0);
return buildBasicNotification(context)
.extend(new Notification.WearableExtender()
.addAction(new Notification.Action(R.mipmap.ic_launcher,
context.getString(R.string.action_a), pendingIntent))
.addAction(new Notification.Action.Builder(R.mipmap.ic_launcher,
context.getString(R.string.reply), pendingIntent)
.addRemoteInput(new RemoteInput.Builder(MainActivity.KEY_REPLY)
.setChoices(new CharSequence[] {
context.getString(R.string.choice_1),
choice2 })
.build())
.build())
.addPage(page2)
.addPage(page3))
.build();
}
}
private static class StylizedTextPreset extends NotificationPreset {
public StylizedTextPreset() {
super(R.string.stylized_text_example);
}
@Override
public Notification buildNotification(Context context) {
Notification.Builder builder = buildBasicNotification(context);
Notification.BigTextStyle style = new Notification.BigTextStyle();
SpannableStringBuilder title = new SpannableStringBuilder();
appendStyled(title, "Stylized", new StyleSpan(Typeface.BOLD_ITALIC));
title.append(" title");
SpannableStringBuilder text = new SpannableStringBuilder("Stylized text: ");
appendStyled(text, "C", new ForegroundColorSpan(Color.RED));
appendStyled(text, "O", new ForegroundColorSpan(Color.GREEN));
appendStyled(text, "L", new ForegroundColorSpan(Color.BLUE));
appendStyled(text, "O", new ForegroundColorSpan(Color.YELLOW));
appendStyled(text, "R", new ForegroundColorSpan(Color.MAGENTA));
appendStyled(text, "S", new ForegroundColorSpan(Color.CYAN));
text.append("; ");
appendStyled(text, "1.25x size", new RelativeSizeSpan(1.25f));
text.append("; ");
appendStyled(text, "0.75x size", new RelativeSizeSpan(0.75f));
text.append("; ");
appendStyled(text, "underline", new UnderlineSpan());
text.append("; ");
appendStyled(text, "strikethrough", new StrikethroughSpan());
text.append("; ");
appendStyled(text, "bold", new StyleSpan(Typeface.BOLD));
text.append("; ");
appendStyled(text, "italic", new StyleSpan(Typeface.ITALIC));
text.append("; ");
appendStyled(text, "sans-serif-thin", new TypefaceSpan("sans-serif-thin"));
text.append("; ");
appendStyled(text, "monospace", new TypefaceSpan("monospace"));
text.append("; ");
appendStyled(text, "sub", new SubscriptSpan());
text.append("script");
appendStyled(text, "super", new SuperscriptSpan());
style.setBigContentTitle(title);
style.bigText(text);
builder.setStyle(style);
return builder.build();
}
private void appendStyled(SpannableStringBuilder builder, String str, Object... spans) {
builder.append(str);
for (Object span : spans) {
builder.setSpan(span, builder.length() - str.length(), builder.length(), 0);
}
}
}
private static class DisplayIntentPreset extends NotificationPreset {
public DisplayIntentPreset() {
super(R.string.display_intent_example);
}
@Override
public Notification buildNotification(Context context) {
Intent displayIntent = new Intent(context, BasicNotificationDisplayActivity.class);
displayIntent.putExtra(BasicNotificationDisplayActivity.EXTRA_TITLE,
context.getString(nameResId));
PendingIntent displayPendingIntent = PendingIntent.getActivity(context,
0, displayIntent, PendingIntent.FLAG_UPDATE_CURRENT);
return buildBasicNotification(context)
.extend(new Notification.WearableExtender()
.setDisplayIntent(displayPendingIntent))
.build();
}
}
private static class MultiSizeDisplayIntentPreset extends NotificationPreset {
public MultiSizeDisplayIntentPreset() {
super(R.string.multisize_display_intent_example);
}
@Override
public Notification buildNotification(Context context) {
PendingIntent pendingIntent = PendingIntent.getActivity(context, 0,
new Intent(context, MainActivity.class), 0);
Intent displayIntent = new Intent(context, BasicNotificationDisplayActivity.class)
.putExtra(BasicNotificationDisplayActivity.EXTRA_TITLE,
context.getString(R.string.xsmall_sized_display));
return buildBasicNotification(context)
.extend(new Notification.WearableExtender()
.setDisplayIntent(PendingIntent.getActivity(context, 0, displayIntent,
PendingIntent.FLAG_UPDATE_CURRENT))
.addPage(createPageForSizePreset(context,
Notification.WearableExtender.SIZE_SMALL,
R.string.small_sized_display, 0))
.addPage(createPageForSizePreset(context,
Notification.WearableExtender.SIZE_MEDIUM,
R.string.medium_sized_display, 1))
.addPage(createPageForSizePreset(context,
Notification.WearableExtender.SIZE_LARGE,
R.string.large_sized_display, 2))
.addPage(createPageForSizePreset(context,
Notification.WearableExtender.SIZE_FULL_SCREEN,
R.string.full_screen_display, 3))
.addPage(createPageForCustomHeight(context, 256,
R.string.dp256_height_display))
.addPage(createPageForCustomHeight(context, 512,
R.string.dp512_height_display))
.addAction(new Notification.Action(R.mipmap.ic_launcher,
context.getString(R.string.action_a), pendingIntent))
.addAction(new Notification.Action(R.mipmap.ic_launcher,
context.getString(R.string.action_b), pendingIntent))
.addAction(new Notification.Action(R.mipmap.ic_launcher,
context.getString(R.string.action_c), pendingIntent))
.addAction(new Notification.Action(R.mipmap.ic_launcher,
context.getString(R.string.action_d), pendingIntent))
.setCustomSizePreset(Notification.WearableExtender.SIZE_XSMALL))
.build();
}
private Notification createPageForCustomHeight(Context context, int heightDisplayDp,
int pageNameResId) {
int contentHeight = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,
heightDisplayDp, context.getResources().getDisplayMetrics());
Intent displayIntent = new Intent(context, BasicNotificationDisplayActivity.class)
.setData(Uri.fromParts("example", "height/" + heightDisplayDp, null))
.putExtra(BasicNotificationDisplayActivity.EXTRA_TITLE,
context.getString(pageNameResId));
return buildBasicNotification(context)
.extend(new Notification.WearableExtender()
.setDisplayIntent(PendingIntent.getActivity(context, 0, displayIntent,
PendingIntent.FLAG_UPDATE_CURRENT))
.setCustomContentHeight(contentHeight))
.build();
}
private Notification createPageForSizePreset(Context context, int sizePreset,
int pageNameResId, int contentAction) {
Intent displayIntent = new Intent(context, BasicNotificationDisplayActivity.class)
.setData(Uri.fromParts("example", "size/" + sizePreset, null))
.putExtra(BasicNotificationDisplayActivity.EXTRA_TITLE,
context.getString(pageNameResId));
return buildBasicNotification(context)
.extend(new Notification.WearableExtender()
.setDisplayIntent(PendingIntent.getActivity(context, 0, displayIntent,
PendingIntent.FLAG_UPDATE_CURRENT))
.setCustomSizePreset(sizePreset)
.setContentAction(contentAction))
.build();
}
}
private static class AnimatedDisplayIntentPreset extends NotificationPreset {
public AnimatedDisplayIntentPreset() {
super(R.string.animated_display_intent_example);
}
@Override
public Notification buildNotification(Context context) {
Intent displayIntent = new Intent(context, AnimatedNotificationDisplayActivity.class);
displayIntent.putExtra(BasicNotificationDisplayActivity.EXTRA_TITLE,
context.getString(nameResId));
PendingIntent displayPendingIntent = PendingIntent.getActivity(context,
0, displayIntent, 0);
return buildBasicNotification(context)
.extend(new Notification.WearableExtender()
.setDisplayIntent(displayPendingIntent))
.build();
}
}
private static class ContentIconPreset extends NotificationPreset {
public ContentIconPreset() {
super(R.string.content_icon_example);
}
@Override
public Notification buildNotification(Context context) {
Notification page2 = buildBasicNotification(context)
.extend(new Notification.WearableExtender()
.setContentIcon(R.drawable.content_icon_small)
.setContentIconGravity(Gravity.START))
.build();
Notification page3 = buildBasicNotification(context)
.extend(new Notification.WearableExtender()
.setContentIcon(R.drawable.content_icon_large))
.build();
Notification page4 = buildBasicNotification(context)
.extend(new Notification.WearableExtender()
.setContentIcon(R.drawable.content_icon_large)
.setContentIconGravity(Gravity.START))
.build();
return buildBasicNotification(context)
.extend(new Notification.WearableExtender()
.setHintHideIcon(true)
.setContentIcon(R.drawable.content_icon_small)
.addPage(page2)
.addPage(page3)
.addPage(page4))
.build();
}
}
}

View File

@@ -0,0 +1,91 @@
/*
* 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.example.android.notifications;
import android.content.Context;
import android.graphics.drawable.GradientDrawable;
import android.support.wearable.view.WearableListView;
import android.util.AttributeSet;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
public class WearableListItemLayout extends LinearLayout implements WearableListView.Item {
private final float mFadedTextAlpha;
private final int mFadedCircleColor;
private final int mChosenCircleColor;
private ImageView mCircle;
private float mScale;
private TextView mName;
public WearableListItemLayout(Context context) {
this(context, null);
}
public WearableListItemLayout(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public WearableListItemLayout(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
mFadedTextAlpha = getResources().getInteger(R.integer.action_text_faded_alpha) / 100f;
mFadedCircleColor = getResources().getColor(R.color.wl_gray);
mChosenCircleColor = getResources().getColor(R.color.wl_blue);
}
@Override
protected void onFinishInflate() {
super.onFinishInflate();
mCircle = (ImageView) findViewById(R.id.circle);
mName = (TextView) findViewById(R.id.name);
}
@Override
public float getProximityMinValue() {
return 1f;
}
@Override
public float getProximityMaxValue() {
return 1.6f;
}
@Override
public float getCurrentProximityValue() {
return mScale;
}
@Override
public void setScalingAnimatorValue(float scale) {
mScale = scale;
mCircle.setScaleX(scale);
mCircle.setScaleY(scale);
}
@Override
public void onScaleUpStart() {
mName.setAlpha(1f);
((GradientDrawable) mCircle.getDrawable()).setColor(mChosenCircleColor);
}
@Override
public void onScaleDownStart() {
((GradientDrawable) mCircle.getDrawable()).setColor(mFadedCircleColor);
mName.setAlpha(mFadedTextAlpha);
}
}