Merge branch 'master' into honeycomb-release
This commit is contained in:
@@ -22,7 +22,6 @@ import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.os.RemoteException;
|
||||
import android.view.IWindowManager;
|
||||
import android.util.Log;
|
||||
|
||||
/**
|
||||
* monkey activity event
|
||||
@@ -57,7 +56,7 @@ public class MonkeyActivityEvent extends MonkeyEvent {
|
||||
public int injectEvent(IWindowManager iwm, IActivityManager iam, int verbose) {
|
||||
Intent intent = getEvent();
|
||||
if (verbose > 0) {
|
||||
System.out.println(":Switch: " + intent.toURI());
|
||||
System.out.println(":Switch: " + intent.toUri(0));
|
||||
}
|
||||
|
||||
if (mAlarmTime != 0){
|
||||
@@ -75,7 +74,7 @@ public class MonkeyActivityEvent extends MonkeyEvent {
|
||||
} catch (SecurityException e) {
|
||||
if (verbose > 0) {
|
||||
System.out.println("** Permissions error starting activity "
|
||||
+ intent.toURI());
|
||||
+ intent.toUri(0));
|
||||
}
|
||||
return MonkeyEvent.INJECT_ERROR_SECURITY_EXCEPTION;
|
||||
}
|
||||
|
||||
@@ -294,7 +294,7 @@ public class MonkeySourceNetwork implements MonkeyEventSource {
|
||||
// Convert the string to an array of KeyEvent's for
|
||||
// the built in keymap.
|
||||
KeyCharacterMap keyCharacterMap = KeyCharacterMap.
|
||||
load(KeyCharacterMap.BUILT_IN_KEYBOARD);
|
||||
load(KeyCharacterMap.VIRTUAL_KEYBOARD);
|
||||
KeyEvent[] events = keyCharacterMap.getEvents(chars);
|
||||
|
||||
// enqueue all the events we just got.
|
||||
|
||||
@@ -48,7 +48,7 @@ public class MonkeySourceRandom implements MonkeyEventSource {
|
||||
private static final int[] SYS_KEYS = {
|
||||
KeyEvent.KEYCODE_HOME, KeyEvent.KEYCODE_BACK,
|
||||
KeyEvent.KEYCODE_CALL, KeyEvent.KEYCODE_ENDCALL,
|
||||
KeyEvent.KEYCODE_VOLUME_UP, KeyEvent.KEYCODE_VOLUME_DOWN,
|
||||
KeyEvent.KEYCODE_VOLUME_UP, KeyEvent.KEYCODE_VOLUME_DOWN, KeyEvent.KEYCODE_VOLUME_MUTE,
|
||||
KeyEvent.KEYCODE_MUTE,
|
||||
};
|
||||
/** If a physical key exists? */
|
||||
|
||||
@@ -151,6 +151,14 @@
|
||||
</intent-filter>
|
||||
</activity>
|
||||
|
||||
<activity android:name=".app.ActivityRecreate"
|
||||
android:label="@string/activity_recreate">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
<category android:name="android.intent.category.SAMPLE_CODE" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
|
||||
<activity android:name=".app.SoftInputModes"
|
||||
android:label="@string/soft_input_modes">
|
||||
<intent-filter>
|
||||
@@ -1856,6 +1864,15 @@
|
||||
</intent-filter>
|
||||
</activity>
|
||||
|
||||
<activity android:name=".view.DragAndDropDemo"
|
||||
android:label="Views/Drag and Drop"
|
||||
android:hardwareAccelerated="false">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
<category android:name="android.intent.category.SAMPLE_CODE" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
|
||||
<!-- ************************************* -->
|
||||
<!-- GRAPHICS SAMPLES -->
|
||||
<!-- ************************************* -->
|
||||
|
||||
@@ -24,7 +24,6 @@
|
||||
android:repeatMode="reverse"/>
|
||||
<objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:duration="1000"
|
||||
android:valueFrom="0"
|
||||
android:valueTo="400"
|
||||
android:valueType="floatType"
|
||||
android:propertyName="y"
|
||||
|
||||
23
samples/ApiDemos/res/anim/color_animator.xml
Normal file
23
samples/ApiDemos/res/anim/color_animator.xml
Normal file
@@ -0,0 +1,23 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- 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.
|
||||
-->
|
||||
|
||||
<objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:duration="1000"
|
||||
android:valueFrom="#0f0"
|
||||
android:valueTo="#00ffff"
|
||||
android:propertyName="color"
|
||||
android:repeatCount="1"
|
||||
android:repeatMode="reverse"/>
|
||||
@@ -16,7 +16,6 @@
|
||||
|
||||
<objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:duration="1000"
|
||||
android:valueFrom="0"
|
||||
android:valueTo="200"
|
||||
android:valueType="floatType"
|
||||
android:propertyName="y"
|
||||
|
||||
37
samples/ApiDemos/res/layout/activity_recreate.xml
Normal file
37
samples/ApiDemos/res/layout/activity_recreate.xml
Normal file
@@ -0,0 +1,37 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- 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.
|
||||
-->
|
||||
|
||||
<!-- Demonstrates starting and stopping a local service.
|
||||
See corresponding Java code com.android.sdk.app.LocalSerice.java. -->
|
||||
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:orientation="vertical" android:padding="4dip"
|
||||
android:gravity="center_horizontal"
|
||||
android:layout_width="match_parent" android:layout_height="match_parent">
|
||||
|
||||
<TextView
|
||||
android:layout_width="match_parent" android:layout_height="wrap_content"
|
||||
android:layout_weight="0"
|
||||
android:paddingBottom="4dip"
|
||||
android:text="@string/activity_recreate_msg"/>
|
||||
|
||||
<Button android:id="@+id/recreate"
|
||||
android:layout_width="wrap_content" android:layout_height="wrap_content"
|
||||
android:text="@string/recreate">
|
||||
<requestFocus />
|
||||
</Button>
|
||||
|
||||
</LinearLayout>
|
||||
93
samples/ApiDemos/res/layout/drag_layout.xml
Normal file
93
samples/ApiDemos/res/layout/drag_layout.xml
Normal file
@@ -0,0 +1,93 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- 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.
|
||||
-->
|
||||
|
||||
<!-- Layout description of the DragAndDrop sample's main activity -->
|
||||
|
||||
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:dot="http://schemas.android.com/apk/res/com.example.android.apis"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
>
|
||||
|
||||
<TextView android:id="@+id/drag_explanation"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/drag_explanation"
|
||||
/>
|
||||
|
||||
<com.example.android.apis.view.DraggableDot
|
||||
android:id="@+id/drag_dot_1"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
dot:radius="64dp"
|
||||
android:padding="15dp"
|
||||
android:layout_below="@id/drag_explanation"
|
||||
/>
|
||||
|
||||
<com.example.android.apis.view.DraggableDot
|
||||
android:id="@+id/drag_dot_2"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
dot:radius="64dp"
|
||||
android:padding="15dp"
|
||||
android:layout_below="@id/drag_explanation"
|
||||
android:layout_toRightOf="@id/drag_dot_1"
|
||||
dot:legend="Drag ANR"
|
||||
dot:anr="thumbnail"
|
||||
/>
|
||||
|
||||
<com.example.android.apis.view.DraggableDot
|
||||
android:id="@+id/drag_dot_3"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
dot:radius="64dp"
|
||||
android:padding="15dp"
|
||||
android:layout_below="@id/drag_dot_1"
|
||||
android:layout_alignLeft="@id/drag_dot_1"
|
||||
dot:legend="Drop ANR"
|
||||
dot:anr="drop"
|
||||
/>
|
||||
|
||||
<com.example.android.apis.view.DraggableDot
|
||||
android:id="@+id/drag_dot_4"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
dot:radius="64dp"
|
||||
android:padding="15dp"
|
||||
android:layout_below="@id/drag_dot_1"
|
||||
android:layout_toRightOf="@id/drag_dot_3"
|
||||
dot:legend="Local"
|
||||
dot:localOnly="true"
|
||||
/>
|
||||
|
||||
<TextView android:id="@+id/drag_result_text"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_below="@id/drag_explanation"
|
||||
android:layout_alignRight="@id/drag_explanation"
|
||||
android:layout_toRightOf="@id/drag_dot_2"
|
||||
/>
|
||||
|
||||
<TextView android:id="@+id/drag_text"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="fill_parent"
|
||||
android:layout_weight="1"
|
||||
android:layout_below="@id/drag_dot_3"
|
||||
android:layout_alignLeft="@id/drag_dot_3"
|
||||
/>
|
||||
|
||||
</RelativeLayout>
|
||||
@@ -32,4 +32,17 @@
|
||||
<attr name="textColor" format="color" />
|
||||
<attr name="textSize" format="dimension" />
|
||||
</declare-styleable>
|
||||
|
||||
<!-- These are attributes used with 'DraggableDot' drawables in
|
||||
view/DragAndDropActivity.java and view/DraggableDot.java -->
|
||||
<declare-styleable name="DraggableDot">
|
||||
<attr name="radius" format="dimension" />
|
||||
<attr name="legend" format="string" />
|
||||
<attr name="localOnly" format="boolean" />
|
||||
<attr name="anr">
|
||||
<enum name="none" value="0" />
|
||||
<enum name="thumbnail" value="1" />
|
||||
<enum name="drop" value="2" />
|
||||
</attr>
|
||||
</declare-styleable>
|
||||
</resources>
|
||||
|
||||
@@ -80,6 +80,11 @@
|
||||
<string name="activity_persistent">App/Activity/Persistent State</string>
|
||||
<string name="persistent_msg">Demonstration of persistent activity state with getPreferences(0).edit() and getPreferences(0).</string>
|
||||
|
||||
<string name="activity_recreate">App/Activity/Recreate</string>
|
||||
<string name="activity_recreate_msg">Demonstration recreating an activity, to have
|
||||
it reconstructed with significant new changes. In this case the theme is changed.</string>
|
||||
<string name="recreate">Recreate</string>
|
||||
|
||||
<string name="activity_receive_result">App/Activity/Receive Result</string>
|
||||
<string name="pick_result">Pick a result to send, or BACK to cancel.</string>
|
||||
<string name="corky">Corky</string>
|
||||
@@ -753,6 +758,12 @@
|
||||
<string name="cheese_hunt_hint">Cheese hunt</string>
|
||||
<string name="open_search">Expand</string>
|
||||
<string name="close_search">Iconify</string>
|
||||
|
||||
<string name="drag_explanation">
|
||||
Longpress on a dot to start a drag, then drop over another dot. The destination
|
||||
dot will append the drag\'s textual conversion to the EditText.
|
||||
</string>
|
||||
|
||||
<!-- ============================== -->
|
||||
<!-- GoogleLogin examples strings -->
|
||||
<!-- ============================== -->
|
||||
|
||||
@@ -21,6 +21,7 @@ package com.example.android.apis.animation;
|
||||
import android.animation.AnimatorInflater;
|
||||
import android.animation.AnimatorSet;
|
||||
import android.animation.ObjectAnimator;
|
||||
import android.graphics.Color;
|
||||
import com.example.android.apis.R;
|
||||
|
||||
import java.util.ArrayList;
|
||||
@@ -73,22 +74,21 @@ public class AnimationLoading extends Activity {
|
||||
|
||||
public MyAnimationView(Context context) {
|
||||
super(context);
|
||||
addBall(100, 0);
|
||||
addBall(250, 0);
|
||||
addBall(400, 0);
|
||||
addBall(50, 50);
|
||||
addBall(200, 50);
|
||||
addBall(350, 50);
|
||||
addBall(500, 50, Color.GREEN);
|
||||
}
|
||||
|
||||
private void createAnimation() {
|
||||
if (animation == null) {
|
||||
ObjectAnimator anim =
|
||||
(ObjectAnimator) AnimatorInflater.
|
||||
ObjectAnimator anim = (ObjectAnimator) AnimatorInflater.
|
||||
loadAnimator(getApplicationContext(), R.anim.object_animator);
|
||||
anim.addUpdateListener(this);
|
||||
anim.setTarget(balls.get(0));
|
||||
|
||||
ValueAnimator fader =
|
||||
(ValueAnimator) AnimatorInflater.loadAnimator(getApplicationContext(),
|
||||
R.anim.animator);
|
||||
ValueAnimator fader = (ValueAnimator) AnimatorInflater.
|
||||
loadAnimator(getApplicationContext(), R.anim.animator);
|
||||
fader.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
|
||||
public void onAnimationUpdate(ValueAnimator animation) {
|
||||
balls.get(1).setAlpha((Float) animation.getAnimatedValue());
|
||||
@@ -100,8 +100,12 @@ public class AnimationLoading extends Activity {
|
||||
R.anim.animator_set);
|
||||
seq.setTarget(balls.get(2));
|
||||
|
||||
ObjectAnimator colorizer = (ObjectAnimator) AnimatorInflater.
|
||||
loadAnimator(getApplicationContext(), R.anim.color_animator);
|
||||
colorizer.setTarget(balls.get(3));
|
||||
|
||||
animation = new AnimatorSet();
|
||||
((AnimatorSet) animation).playTogether(anim, fader, seq);
|
||||
((AnimatorSet) animation).playTogether(anim, fader, seq, colorizer);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -110,25 +114,34 @@ public class AnimationLoading extends Activity {
|
||||
animation.start();
|
||||
}
|
||||
|
||||
private ShapeHolder addBall(float x, float y) {
|
||||
private ShapeHolder createBall(float x, float y) {
|
||||
OvalShape circle = new OvalShape();
|
||||
circle.resize(BALL_SIZE, BALL_SIZE);
|
||||
ShapeDrawable drawable = new ShapeDrawable(circle);
|
||||
ShapeHolder shapeHolder = new ShapeHolder(drawable);
|
||||
shapeHolder.setX(x);
|
||||
shapeHolder.setY(y);
|
||||
return shapeHolder;
|
||||
}
|
||||
|
||||
private void addBall(float x, float y, int color) {
|
||||
ShapeHolder shapeHolder = createBall(x, y);
|
||||
shapeHolder.setColor(color);
|
||||
balls.add(shapeHolder);
|
||||
}
|
||||
|
||||
private void addBall(float x, float y) {
|
||||
ShapeHolder shapeHolder = createBall(x, y);
|
||||
int red = (int)(100 + Math.random() * 155);
|
||||
int green = (int)(100 + Math.random() * 155);
|
||||
int blue = (int)(100 + Math.random() * 155);
|
||||
int color = 0xff000000 | red << 16 | green << 8 | blue;
|
||||
Paint paint = drawable.getPaint();
|
||||
Paint paint = shapeHolder.getShape().getPaint();
|
||||
int darkColor = 0xff000000 | red/4 << 16 | green/4 << 8 | blue/4;
|
||||
RadialGradient gradient = new RadialGradient(37.5f, 12.5f,
|
||||
50f, color, darkColor, Shader.TileMode.CLAMP);
|
||||
paint.setShader(gradient);
|
||||
shapeHolder.setPaint(paint);
|
||||
balls.add(shapeHolder);
|
||||
return shapeHolder;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -63,6 +63,7 @@ public class ShapeHolder {
|
||||
return color;
|
||||
}
|
||||
public void setColor(int value) {
|
||||
shape.getPaint().setColor(value);
|
||||
color = value;
|
||||
}
|
||||
public void setGradient(RadialGradient value) {
|
||||
|
||||
@@ -0,0 +1,73 @@
|
||||
/*
|
||||
* 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.example.android.apis.app;
|
||||
|
||||
import com.example.android.apis.R;
|
||||
import com.example.android.apis.app.LocalServiceActivities.Controller;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.util.Log;
|
||||
import android.view.View;
|
||||
import android.view.View.OnClickListener;
|
||||
import android.widget.Button;
|
||||
|
||||
public class ActivityRecreate extends Activity {
|
||||
int mCurTheme;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
if (savedInstanceState != null) {
|
||||
mCurTheme = savedInstanceState.getInt("theme");
|
||||
|
||||
// Switch to a new theme different from last theme.
|
||||
switch (mCurTheme) {
|
||||
case android.R.style.Theme_Holo_Light:
|
||||
mCurTheme = android.R.style.Theme_Holo_Dialog;
|
||||
break;
|
||||
case android.R.style.Theme_Holo_Dialog:
|
||||
mCurTheme = android.R.style.Theme_Holo;
|
||||
break;
|
||||
default:
|
||||
mCurTheme = android.R.style.Theme_Holo_Light;
|
||||
break;
|
||||
}
|
||||
setTheme(mCurTheme);
|
||||
}
|
||||
|
||||
setContentView(R.layout.activity_recreate);
|
||||
|
||||
// Watch for button clicks.
|
||||
Button button = (Button)findViewById(R.id.recreate);
|
||||
button.setOnClickListener(mRecreateListener);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onSaveInstanceState(Bundle savedInstanceState) {
|
||||
super.onSaveInstanceState(savedInstanceState);
|
||||
savedInstanceState.putInt("theme", mCurTheme);
|
||||
}
|
||||
|
||||
private OnClickListener mRecreateListener = new OnClickListener() {
|
||||
public void onClick(View v) {
|
||||
recreate();
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
/*
|
||||
* 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.example.android.apis.view;
|
||||
|
||||
import com.example.android.apis.R;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.os.Bundle;
|
||||
import android.view.DragEvent;
|
||||
import android.view.View;
|
||||
import android.widget.TextView;
|
||||
|
||||
public class DragAndDropDemo extends Activity {
|
||||
TextView mResultText;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.drag_layout);
|
||||
|
||||
TextView text = (TextView) findViewById(R.id.drag_text);
|
||||
DraggableDot dot = (DraggableDot) findViewById(R.id.drag_dot_1);
|
||||
dot.setReportView(text);
|
||||
dot = (DraggableDot) findViewById(R.id.drag_dot_2);
|
||||
dot.setReportView(text);
|
||||
dot = (DraggableDot) findViewById(R.id.drag_dot_3);
|
||||
dot.setReportView(text);
|
||||
dot = (DraggableDot) findViewById(R.id.drag_dot_4);
|
||||
dot.setReportView(text);
|
||||
|
||||
mResultText = (TextView) findViewById(R.id.drag_result_text);
|
||||
mResultText.setOnDragListener(new View.OnDragListener() {
|
||||
@Override
|
||||
public boolean onDrag(View v, DragEvent event) {
|
||||
final int action = event.getAction();
|
||||
if (action == DragEvent.ACTION_DRAG_ENDED) {
|
||||
final boolean dropped = event.getResult();
|
||||
mResultText.setText(dropped ? "Dropped!" : "No drop");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,266 @@
|
||||
/*
|
||||
* 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.example.android.apis.view;
|
||||
|
||||
import com.example.android.apis.R;
|
||||
|
||||
import android.content.ClipData;
|
||||
import android.content.Context;
|
||||
import android.content.res.TypedArray;
|
||||
import android.graphics.*;
|
||||
import android.os.SystemClock;
|
||||
import android.text.TextPaint;
|
||||
import android.util.AttributeSet;
|
||||
import android.util.Log;
|
||||
import android.view.DragEvent;
|
||||
import android.view.View;
|
||||
import android.widget.TextView;
|
||||
|
||||
public class DraggableDot extends View {
|
||||
static final String TAG = "DraggableDot";
|
||||
|
||||
private boolean mDragInProgress;
|
||||
private boolean mHovering;
|
||||
private boolean mAcceptsDrag;
|
||||
TextView mReportView;
|
||||
|
||||
private Paint mPaint;
|
||||
private TextPaint mLegendPaint;
|
||||
private Paint mGlow;
|
||||
private static final int NUM_GLOW_STEPS = 10;
|
||||
private static final int GREEN_STEP = 0x0000FF00 / NUM_GLOW_STEPS;
|
||||
private static final int WHITE_STEP = 0x00FFFFFF / NUM_GLOW_STEPS;
|
||||
private static final int ALPHA_STEP = 0xFF000000 / NUM_GLOW_STEPS;
|
||||
|
||||
int mRadius;
|
||||
int mAnrType;
|
||||
boolean mLocalOnly;
|
||||
CharSequence mLegend;
|
||||
|
||||
static final int ANR_NONE = 0;
|
||||
static final int ANR_THUMBNAIL = 1;
|
||||
static final int ANR_DROP = 2;
|
||||
|
||||
void sleepSixSeconds() {
|
||||
// hang forever; good for producing ANRs
|
||||
long start = SystemClock.uptimeMillis();
|
||||
do {
|
||||
try { Thread.sleep(1000); } catch (InterruptedException e) {}
|
||||
} while (SystemClock.uptimeMillis() < start + 6000);
|
||||
}
|
||||
|
||||
// Thumbnail builder that can ANR if desired
|
||||
class ANRThumbBuilder extends DragThumbnailBuilder {
|
||||
boolean mDoAnr;
|
||||
|
||||
public ANRThumbBuilder(View view, boolean doAnr) {
|
||||
super(view);
|
||||
mDoAnr = doAnr;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDrawThumbnail(Canvas canvas) {
|
||||
if (mDoAnr) {
|
||||
sleepSixSeconds();
|
||||
}
|
||||
super.onDrawThumbnail(canvas);
|
||||
}
|
||||
}
|
||||
|
||||
public DraggableDot(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
|
||||
setFocusable(true);
|
||||
setClickable(true);
|
||||
|
||||
mLegend = "";
|
||||
|
||||
mPaint = new Paint();
|
||||
mPaint.setAntiAlias(true);
|
||||
mPaint.setStrokeWidth(6);
|
||||
mPaint.setColor(0xFFD00000);
|
||||
|
||||
mLegendPaint = new TextPaint();
|
||||
mLegendPaint.setAntiAlias(true);
|
||||
mLegendPaint.setTextAlign(Paint.Align.CENTER);
|
||||
mLegendPaint.setColor(0xFFF0F0FF);
|
||||
|
||||
mGlow = new Paint();
|
||||
mGlow.setAntiAlias(true);
|
||||
mGlow.setStrokeWidth(1);
|
||||
mGlow.setStyle(Paint.Style.STROKE);
|
||||
|
||||
// look up any layout-defined attributes
|
||||
TypedArray a = context.obtainStyledAttributes(attrs,
|
||||
R.styleable.DraggableDot);
|
||||
|
||||
final int N = a.getIndexCount();
|
||||
for (int i = 0; i < N; i++) {
|
||||
int attr = a.getIndex(i);
|
||||
switch (attr) {
|
||||
case R.styleable.DraggableDot_radius: {
|
||||
mRadius = a.getDimensionPixelSize(attr, 0);
|
||||
} break;
|
||||
|
||||
case R.styleable.DraggableDot_legend: {
|
||||
mLegend = a.getText(attr);
|
||||
} break;
|
||||
|
||||
case R.styleable.DraggableDot_anr: {
|
||||
mAnrType = a.getInt(attr, 0);
|
||||
} break;
|
||||
|
||||
case R.styleable.DraggableDot_localOnly: {
|
||||
mLocalOnly = a.getBoolean(attr, false);
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
Log.i(TAG, "DraggableDot @ " + this + " : radius=" + mRadius + " legend='" + mLegend
|
||||
+ "' anr=" + mAnrType + " local=" + mLocalOnly);
|
||||
|
||||
setOnLongClickListener(new View.OnLongClickListener() {
|
||||
public boolean onLongClick(View v) {
|
||||
ClipData data = ClipData.newPlainText("dot", null, "Dot : " + v.toString());
|
||||
v.startDrag(data, new ANRThumbBuilder(v, mAnrType == ANR_THUMBNAIL),
|
||||
mLocalOnly, (Object)v);
|
||||
return true;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void setReportView(TextView view) {
|
||||
mReportView = view;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDraw(Canvas canvas) {
|
||||
float wf = getWidth();
|
||||
float hf = getHeight();
|
||||
final float cx = wf/2;
|
||||
final float cy = hf/2;
|
||||
wf -= getPaddingLeft() + getPaddingRight();
|
||||
hf -= getPaddingTop() + getPaddingBottom();
|
||||
float rad = (wf < hf) ? wf/2 : hf/2;
|
||||
canvas.drawCircle(cx, cy, rad, mPaint);
|
||||
|
||||
if (mLegend != null && mLegend.length() > 0) {
|
||||
canvas.drawText(mLegend, 0, mLegend.length(),
|
||||
cx, cy + mLegendPaint.getFontSpacing()/2,
|
||||
mLegendPaint);
|
||||
}
|
||||
|
||||
// if we're in the middle of a drag, light up as a potential target
|
||||
if (mDragInProgress && mAcceptsDrag) {
|
||||
for (int i = NUM_GLOW_STEPS; i > 0; i--) {
|
||||
int color = (mHovering) ? WHITE_STEP : GREEN_STEP;
|
||||
color = i*(color | ALPHA_STEP);
|
||||
mGlow.setColor(color);
|
||||
canvas.drawCircle(cx, cy, rad, mGlow);
|
||||
rad -= 0.5f;
|
||||
canvas.drawCircle(cx, cy, rad, mGlow);
|
||||
rad -= 0.5f;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onMeasure(int widthSpec, int heightSpec) {
|
||||
int totalDiameter = 2*mRadius + getPaddingLeft() + getPaddingRight();
|
||||
setMeasuredDimension(totalDiameter, totalDiameter);
|
||||
}
|
||||
|
||||
/**
|
||||
* Drag and drop
|
||||
*/
|
||||
@Override
|
||||
public boolean onDragEvent(DragEvent event) {
|
||||
boolean result = false;
|
||||
switch (event.getAction()) {
|
||||
case DragEvent.ACTION_DRAG_STARTED: {
|
||||
// claim to accept any dragged content
|
||||
Log.i(TAG, "Drag started, event=" + event);
|
||||
// cache whether we accept the drag to return for LOCATION events
|
||||
mDragInProgress = true;
|
||||
mAcceptsDrag = result = true;
|
||||
// Redraw in the new visual state if we are a potential drop target
|
||||
if (mAcceptsDrag) {
|
||||
invalidate();
|
||||
}
|
||||
} break;
|
||||
|
||||
case DragEvent.ACTION_DRAG_ENDED: {
|
||||
Log.i(TAG, "Drag ended.");
|
||||
if (mAcceptsDrag) {
|
||||
invalidate();
|
||||
}
|
||||
mDragInProgress = false;
|
||||
mHovering = false;
|
||||
} break;
|
||||
|
||||
case DragEvent.ACTION_DRAG_LOCATION: {
|
||||
// we returned true to DRAG_STARTED, so return true here
|
||||
Log.i(TAG, "... seeing drag locations ...");
|
||||
result = mAcceptsDrag;
|
||||
} break;
|
||||
|
||||
case DragEvent.ACTION_DROP: {
|
||||
Log.i(TAG, "Got a drop! dot=" + this + " event=" + event);
|
||||
if (mAnrType == ANR_DROP) {
|
||||
sleepSixSeconds();
|
||||
}
|
||||
processDrop(event);
|
||||
result = true;
|
||||
} break;
|
||||
|
||||
case DragEvent.ACTION_DRAG_ENTERED: {
|
||||
Log.i(TAG, "Entered dot @ " + this);
|
||||
mHovering = true;
|
||||
invalidate();
|
||||
} break;
|
||||
|
||||
case DragEvent.ACTION_DRAG_EXITED: {
|
||||
Log.i(TAG, "Exited dot @ " + this);
|
||||
mHovering = false;
|
||||
invalidate();
|
||||
} break;
|
||||
|
||||
default:
|
||||
Log.i(TAG, "other drag event: " + event);
|
||||
result = mAcceptsDrag;
|
||||
break;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private void processDrop(DragEvent event) {
|
||||
final ClipData data = event.getClipData();
|
||||
final int N = data.getItemCount();
|
||||
for (int i = 0; i < N; i++) {
|
||||
ClipData.Item item = data.getItem(i);
|
||||
Log.i(TAG, "Dropped item " + i + " : " + item);
|
||||
if (mReportView != null) {
|
||||
String text = item.coerceToText(getContext()).toString();
|
||||
if (event.getLocalState() == (Object) this) {
|
||||
text += " : Dropped on self!";
|
||||
}
|
||||
mReportView.setText(text);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user