Merge "Bringing back the pocket."

This commit is contained in:
Daniel Sandler
2011-02-09 06:19:58 -08:00
committed by Android (Google) Code Review
6 changed files with 176 additions and 94 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 324 B

View File

@@ -0,0 +1,21 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2011 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.
-->
<bitmap
xmlns:android="http://schemas.android.com/apk/res/android"
android:tileMode="repeat"
android:src="@drawable/pocket_drag_pattern"
/>

View File

@@ -91,6 +91,15 @@
</RelativeLayout>
</FrameLayout>
<view
class="com.android.systemui.statusbar.tablet.ShirtPocket$DropZone"
android:id="@+id/drop_target"
android:layout_width="512dp"
android:layout_height="@*android:dimen/status_bar_height"
android:background="@drawable/pocket_drag_bg"
android:layout_gravity="right"
/>
<FrameLayout
android:id="@+id/bar_shadow_holder"
android:layout_width="match_parent"

View File

@@ -41,6 +41,15 @@
android:src="@drawable/ic_sysbar_ime_default"
android:visibility="gone"
/>
<com.android.systemui.statusbar.tablet.ShirtPocket
android:id="@+id/shirt_pocket"
android:layout_width="@*android:dimen/status_bar_height"
android:layout_height="@*android:dimen/status_bar_height"
android:background="#FFFF0000"
android:visibility="gone"
/>
<com.android.systemui.statusbar.tablet.NotificationIconArea
android:id="@+id/notificationIcons"
android:layout_width="wrap_content"

View File

@@ -16,26 +16,28 @@
package com.android.systemui.statusbar.tablet;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.ObjectAnimator;
import android.content.Context;
import android.util.Slog;
import android.view.View;
import android.util.AttributeSet;
import android.widget.ImageView;
import android.widget.TextView;
import android.view.DragEvent;
import android.view.MotionEvent;
import android.content.ClipData;
import android.content.ClipDescription;
import android.graphics.Paint;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Point;
import android.view.WindowManager;
import android.widget.FrameLayout;
import android.view.WindowManagerImpl;
import android.graphics.Paint;
import android.graphics.PixelFormat;
import android.graphics.Point;
import android.util.AttributeSet;
import android.util.Slog;
import android.view.DragEvent;
import android.view.Gravity;
import android.view.MotionEvent;
import android.view.View;
import android.view.WindowManager;
import android.view.WindowManagerImpl;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.TextView;
import com.android.systemui.R;
@@ -45,10 +47,80 @@ public class ShirtPocket extends ImageView {
private ClipData mClipping = null;
private View mWindow = null;
private ImageView mPreviewIcon;
private TextView mDescription;
private TextView mAltText;
public static class DropZone extends View {
ShirtPocket mPocket;
public DropZone(Context context, AttributeSet attrs) {
super(context, attrs);
}
public void setPocket(ShirtPocket p) {
mPocket = p;
}
public void onAttachedToWindow() {
super.onAttachedToWindow();
if (mPocket.holding()) {
show(false);
} else {
hide(false);
}
}
// Drag API notes: we must be visible to receive drag events
private void show(boolean animate) {
setTranslationY(0f);
if (animate) {
setAlpha(0f);
ObjectAnimator.ofFloat(this, "alpha", 0f, 1f).start();
} else {
setAlpha(1f);
}
}
private void hide(boolean animate) {
AnimatorListenerAdapter onEnd = new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator _a) {
DropZone.this.setTranslationY(getHeight() + 2);
DropZone.this.setAlpha(0f);
}
};
if (animate) {
Animator a = ObjectAnimator.ofFloat(this, "alpha", getAlpha(), 0f);
a.addListener(onEnd);
a.start();
} else {
onEnd.onAnimationEnd(null);
}
}
@Override
public boolean onDragEvent(DragEvent event) {
if (DEBUG) Slog.d(TAG, "onDragEvent: " + event);
switch (event.getAction()) {
// We want to appear whenever a potential drag takes off from anywhere in the UI.
case DragEvent.ACTION_DRAG_STARTED:
show(true);
break;
case DragEvent.ACTION_DRAG_ENTERED:
if (DEBUG) Slog.d(TAG, "entered!");
// XXX: TODO
break;
case DragEvent.ACTION_DRAG_EXITED:
if (DEBUG) Slog.d(TAG, "exited!");
break;
case DragEvent.ACTION_DROP:
if (DEBUG) Slog.d(TAG, "dropped!");
mPocket.stash(event.getClipData());
break;
case DragEvent.ACTION_DRAG_ENDED:
hide(true);
break;
}
return true; // we want everything, thank you
}
}
public ShirtPocket(Context context, AttributeSet attrs) {
super(context, attrs);
@@ -58,74 +130,66 @@ public class ShirtPocket extends ImageView {
ObjectAnimator mAnimHide, mAnimShow;
protected void onAttachedToWindow() {
// Drag API notes: we must be visible to receive drag events
setVisibility(View.VISIBLE);
refresh();
setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
if (mClipping != null) {
if (mWindow.getVisibility() == View.VISIBLE) hideWindow();
else showWindow();
}
}
});
}
private void refresh() {
setClickable(mClipping != null);
// XXX: TODO
}
private void showWindow() {
getHandler().post(new Runnable() {
public void run() {
mWindow.setVisibility(View.VISIBLE);
refresh();
}
});
}
private void hideWindow() {
getHandler().post(new Runnable() {
public void run() {
mWindow.setVisibility(View.GONE);
refresh();
}
});
}
private void hideWindowInJustASec() {
getHandler().postDelayed(new Runnable() {
public void run() {
mWindow.setVisibility(View.GONE);
refresh();
}
},
250);
public boolean holding() {
return (mClipping != null);
}
private void stash(ClipData clipping) {
mClipping = clipping;
if (mClipping != null) {
setVisibility(View.VISIBLE);
Bitmap icon = mClipping.getIcon();
mDescription.setText(mClipping.getDescription().getLabel());
// mDescription.setText(mClipping.getDescription().getLabel());
if (icon != null) {
mPreviewIcon.setImageBitmap(icon);
mPreviewIcon.setVisibility(View.VISIBLE);
mAltText.setVisibility(View.GONE);
setImageBitmap(icon);
} else {
mPreviewIcon.setVisibility(View.GONE);
mAltText.setVisibility(View.VISIBLE);
if (mClipping.getItemCount() > 0) {
// TODO: figure out how to visualize every kind of ClipData!
mAltText.setText(mClipping.getItemAt(0).coerceToText(getContext()));
//mAltText.setText(mClipping.getItemAt(0).coerceToText(getContext()));
}
}
} else {
setVisibility(View.GONE);
}
}
@Override
public boolean onTouchEvent(MotionEvent ev) {
final int action = ev.getAction();
if (action == MotionEvent.ACTION_DOWN) {
final ClipData clip = mClipping;
if (clip != null) {
final Bitmap icon = clip.getIcon();
DragShadowBuilder shadow;
if (icon != null) {
shadow = new DragShadowBuilder(this) {
public void onProvideShadowMetrics(Point shadowSize, Point shadowTouchPoint) {
shadowSize.set(icon.getWidth(), icon.getHeight());
shadowTouchPoint.set(shadowSize.x / 2, shadowSize.y / 2);
}
public void onDrawShadow(Canvas canvas) {
canvas.drawBitmap(icon, 0, 0, new Paint());
}
};
} else {
// uhhh, what now?
shadow = new DragShadowBuilder(this);
}
startDrag(clip, shadow, null, 0);
// TODO: only discard the clipping if it was accepted
stash(null);
return true;
}
}
return false;
}
/*
private boolean isInViewContentArea(View v, int x, int y) {
final int l = v.getPaddingLeft();
final int r = v.getWidth() - v.getPaddingRight();
@@ -167,38 +231,12 @@ public class ShirtPocket extends ImageView {
// TODO: only discard the clipping if it was accepted
stash(null);
hideWindowInJustASec(); // will refresh the icon
return true;
}
}
return false;
}
};
public boolean onDragEvent(DragEvent event) {
if (DEBUG) Slog.d(TAG, "onDragEvent: " + event);
switch (event.getAction()) {
// We want to appear whenever a potential drag takes off from anywhere in the UI.
case DragEvent.ACTION_DRAG_STARTED:
// XXX: TODO
break;
case DragEvent.ACTION_DRAG_ENTERED:
if (DEBUG) Slog.d(TAG, "entered!");
// XXX: TODO
break;
case DragEvent.ACTION_DRAG_EXITED:
if (DEBUG) Slog.d(TAG, "exited!");
setVisibility(mClipping == null ? View.GONE : View.VISIBLE);
break;
case DragEvent.ACTION_DROP:
if (DEBUG) Slog.d(TAG, "dropped!");
stash(event.getClipData());
break;
case DragEvent.ACTION_DRAG_ENDED:
break;
}
return true; // we want everything, thank you
}
*/
}

View File

@@ -392,6 +392,11 @@ public class TabletStatusBar extends StatusBar implements
// for redirecting errant bar taps to the IME
mFakeSpaceBar = sb.findViewById(R.id.fake_space_bar);
// drag and drop pocket
ShirtPocket p = (ShirtPocket) sb.findViewById(R.id.shirt_pocket);
ShirtPocket.DropZone z = (ShirtPocket.DropZone) sb.findViewById(R.id.drop_target);
z.setPocket(p);
// "shadows" of the status bar features, for lights-out mode
mShadow = sb.findViewById(R.id.bar_shadow);
mShadow.setOnTouchListener(