250 lines
9.7 KiB
Java
250 lines
9.7 KiB
Java
/*
|
|
* 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.
|
|
*/
|
|
|
|
package com.android.notificationstudio;
|
|
|
|
import android.animation.Animator;
|
|
import android.animation.AnimatorListenerAdapter;
|
|
import android.app.Activity;
|
|
import android.app.Notification;
|
|
import android.app.NotificationManager;
|
|
import android.content.Context;
|
|
import android.os.Build;
|
|
import android.os.Bundle;
|
|
import android.os.Handler;
|
|
import android.util.DisplayMetrics;
|
|
import android.util.Log;
|
|
import android.view.Menu;
|
|
import android.view.MenuInflater;
|
|
import android.view.MenuItem;
|
|
import android.view.MotionEvent;
|
|
import android.view.View;
|
|
import android.view.View.OnLayoutChangeListener;
|
|
import android.view.ViewGroup;
|
|
import android.view.inputmethod.InputMethodManager;
|
|
import android.widget.EditText;
|
|
import android.widget.FrameLayout;
|
|
import android.widget.FrameLayout.LayoutParams;
|
|
import android.widget.ImageView;
|
|
import android.widget.LinearLayout;
|
|
import android.widget.RemoteViews;
|
|
import android.widget.TextView;
|
|
|
|
import com.android.notificationstudio.action.ShareCodeAction;
|
|
import com.android.notificationstudio.action.ShareMockupAction;
|
|
import com.android.notificationstudio.editor.Editors;
|
|
import com.android.notificationstudio.generator.NotificationGenerator;
|
|
import com.android.notificationstudio.model.EditableItem;
|
|
import com.android.notificationstudio.model.EditableItemConstants;
|
|
|
|
import java.util.concurrent.ExecutorService;
|
|
import java.util.concurrent.Executors;
|
|
|
|
public class NotificationStudioActivity extends Activity implements EditableItemConstants{
|
|
private static final String TAG = NotificationStudioActivity.class.getSimpleName();
|
|
private static final int PREVIEW_NOTIFICATION = 1;
|
|
private static final int REFRESH_DELAY = 50;
|
|
private static final ExecutorService BACKGROUND = Executors.newSingleThreadExecutor();
|
|
|
|
private boolean mRefreshPending;
|
|
|
|
private final Handler mHandler = new Handler();
|
|
private final Runnable mRefreshNotificationInner = new Runnable() {
|
|
public void run() {
|
|
refreshNotificationInner();
|
|
}};
|
|
|
|
@Override
|
|
public void onCreate(Bundle savedInstanceState) {
|
|
super.onCreate(savedInstanceState);
|
|
|
|
getWindow().setBackgroundDrawableResource(android.R.color.black);
|
|
setContentView(R.layout.studio);
|
|
initPreviewScroller();
|
|
|
|
EditableItem.initIfNecessary(this);
|
|
|
|
initEditors();
|
|
}
|
|
|
|
private void initPreviewScroller() {
|
|
|
|
MaxHeightScrollView preview = (MaxHeightScrollView) findViewById(R.id.preview_scroller);
|
|
if (preview == null)
|
|
return;
|
|
final int margin = ((ViewGroup.MarginLayoutParams) preview.getLayoutParams()).bottomMargin;
|
|
preview.addOnLayoutChangeListener(new OnLayoutChangeListener(){
|
|
public void onLayoutChange(View v, int left, int top, int right, int bottom,
|
|
int oldLeft, int oldTop, int oldRight, int oldBottom) {
|
|
// animate preview height changes
|
|
if (oldBottom != bottom) {
|
|
final View e = findViewById(R.id.editors);
|
|
final int y = bottom + margin;
|
|
e.animate()
|
|
.translationY(y - oldBottom)
|
|
.setListener(new AnimatorListenerAdapter() {
|
|
public void onAnimationEnd(Animator animation) {
|
|
FrameLayout.LayoutParams lp = (LayoutParams) e.getLayoutParams();
|
|
lp.topMargin = y;
|
|
e.setTranslationY(0);
|
|
e.setLayoutParams(lp);
|
|
}
|
|
});
|
|
}
|
|
}});
|
|
|
|
// limit the max height for preview, leave room for editors + soft keyboard
|
|
DisplayMetrics dm = new DisplayMetrics();
|
|
getWindowManager().getDefaultDisplay().getMetrics(dm);
|
|
float actualHeight = dm.heightPixels / dm.ydpi;
|
|
float pct = actualHeight < 3.5 ? .32f :
|
|
actualHeight < 4 ? .35f :
|
|
.38f;
|
|
preview.setMaxHeight((int)(dm.heightPixels * pct));
|
|
}
|
|
|
|
private void initEditors() {
|
|
LinearLayout items = (LinearLayout) findViewById(R.id.items);
|
|
items.removeAllViews();
|
|
String currentCategory = null;
|
|
for (EditableItem item : EditableItem.values()) {
|
|
String itemCategory = item.getCategory(this);
|
|
if (!itemCategory.equals(currentCategory)) {
|
|
View dividerView = getLayoutInflater().inflate(R.layout.divider, null);
|
|
((TextView) dividerView.findViewById(R.id.divider_text)).setText(itemCategory);
|
|
items.addView(dividerView);
|
|
currentCategory = itemCategory;
|
|
}
|
|
View editorView = Editors.newEditor(this, items, item);
|
|
if (editorView != null)
|
|
items.addView(editorView);
|
|
}
|
|
refreshNotification();
|
|
}
|
|
|
|
@Override
|
|
protected void onRestoreInstanceState(Bundle savedInstanceState) {
|
|
// we'll take care of restoring state
|
|
}
|
|
|
|
public void refreshNotification() {
|
|
mRefreshPending = true;
|
|
mHandler.postDelayed(mRefreshNotificationInner, REFRESH_DELAY);
|
|
}
|
|
|
|
private void refreshNotificationInner() {
|
|
if (!mRefreshPending) {
|
|
return;
|
|
}
|
|
final Notification notification = NotificationGenerator.build(this);
|
|
ViewGroup oneU = (ViewGroup) findViewById(R.id.oneU);
|
|
ViewGroup fourU = (ViewGroup) findViewById(R.id.fourU);
|
|
View oneUView = refreshRemoteViews(oneU, notification.contentView);
|
|
if (Build.VERSION.SDK_INT >= 16)
|
|
refreshRemoteViews(fourU, notification.bigContentView);
|
|
else if (Build.VERSION.SDK_INT >= 11) {
|
|
ImageView largeIcon = (ImageView) findViewById(R.id.large_icon);
|
|
largeIcon.setVisibility(notification.largeIcon == null ? View.GONE : View.VISIBLE);
|
|
if (notification.largeIcon != null)
|
|
largeIcon.setImageBitmap(notification.largeIcon);
|
|
} else if (oneUView != null) {
|
|
oneUView.setBackgroundColor(getResources().getColor(R.color.gb_background));
|
|
oneUView.setMinimumHeight(100);
|
|
}
|
|
mRefreshPending = false;
|
|
|
|
// this can take a while, run on a background thread
|
|
BACKGROUND.submit(new Runnable() {
|
|
public void run() {
|
|
NotificationManager mgr =
|
|
(NotificationManager) getSystemService(NOTIFICATION_SERVICE);
|
|
try {
|
|
mgr.notify(PREVIEW_NOTIFICATION, notification);
|
|
} catch (Throwable t) {
|
|
Log.w(TAG, "Error displaying notification", t);
|
|
}
|
|
}});
|
|
}
|
|
|
|
private View refreshRemoteViews(ViewGroup parent, RemoteViews remoteViews) {
|
|
parent.removeAllViews();
|
|
if (remoteViews != null) {
|
|
parent.setVisibility(View.VISIBLE);
|
|
try {
|
|
View v = remoteViews.apply(this, parent);
|
|
parent.addView(v);
|
|
return v;
|
|
} catch (Exception e) {
|
|
TextView exceptionView = new TextView(this);
|
|
exceptionView.setText(e.getClass().getSimpleName() + ": " + e.getMessage());
|
|
parent.addView(exceptionView);
|
|
return exceptionView;
|
|
}
|
|
} else {
|
|
parent.setVisibility(View.GONE);
|
|
return null;
|
|
}
|
|
}
|
|
|
|
// action bar setup
|
|
@Override
|
|
public boolean onCreateOptionsMenu(Menu menu) {
|
|
MenuInflater inflater = getMenuInflater();
|
|
inflater.inflate(R.menu.action_bar, menu);
|
|
return true;
|
|
}
|
|
|
|
@Override
|
|
public boolean onOptionsItemSelected(MenuItem item) {
|
|
switch (item.getItemId()) {
|
|
case R.id.action_share_code:
|
|
ShareCodeAction.launch(this, item.getTitle());
|
|
return true;
|
|
case R.id.action_share_mockup:
|
|
ShareMockupAction.launch(this, item.getTitle());
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
// hides the soft keyboard more aggressively when leaving text editors
|
|
@Override
|
|
public boolean dispatchTouchEvent(MotionEvent event) {
|
|
View v = getCurrentFocus();
|
|
boolean ret = super.dispatchTouchEvent(event);
|
|
|
|
if (v instanceof EditText) {
|
|
View currentFocus = getCurrentFocus();
|
|
int screenCoords[] = new int[2];
|
|
currentFocus.getLocationOnScreen(screenCoords);
|
|
float x = event.getRawX() + currentFocus.getLeft() - screenCoords[0];
|
|
float y = event.getRawY() + currentFocus.getTop() - screenCoords[1];
|
|
|
|
if (event.getAction() == MotionEvent.ACTION_UP
|
|
&& (x < currentFocus.getLeft() ||
|
|
x >= currentFocus.getRight() ||
|
|
y < currentFocus.getTop() ||
|
|
y > currentFocus.getBottom())) {
|
|
InputMethodManager imm =
|
|
(InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
|
|
imm.hideSoftInputFromWindow(getWindow().getCurrentFocus().getWindowToken(), 0);
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
}
|