/* * Copyright (C) 2014 The AppCan Open Source Project. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. * */ package org.zywx.wbpalmstar.platform.myspace; import org.zywx.wbpalmstar.base.ResoureFinder; import org.zywx.wbpalmstar.engine.ESystemInfo; import org.zywx.wbpalmstar.platform.myspace.GSenseView.OnBallFallIntoCallback; import android.content.Context; import android.graphics.Canvas; import android.graphics.PixelFormat; import android.graphics.drawable.Drawable; import android.hardware.Sensor; import android.hardware.SensorEvent; import android.hardware.SensorEventListener; import android.hardware.SensorManager; import android.util.AttributeSet; import android.util.DisplayMetrics; import android.view.Gravity; import android.view.MotionEvent; import android.view.View; import android.view.ViewConfiguration; import android.view.WindowManager; public class DragableView extends View implements SensorEventListener { public static final String TAG = "DragableView"; private DisplayMetrics dm; private WindowManager windowManager; private WindowManager.LayoutParams params; private ResoureFinder finder; float currentX; float currentY; private SensorManager sensorManager; private Sensor sensor; private GSenseView gSenseView; private OnGSBallFallListener listener; private boolean isAddedSenseView = false; private int cpuMHZ; public DragableView(WindowManager windowManager, Context context) { super(context); this.windowManager = windowManager; init(); } public DragableView(Context context, AttributeSet attrs) { super(context, attrs); init(); } public void setGSBallFallListener(OnGSBallFallListener fallListener) { listener = fallListener; } public WindowManager.LayoutParams getLayoutParams() { return params; } private void init() { finder = ResoureFinder.getInstance(getContext()); cpuMHZ = ESystemInfo.getIntence().cpuMHZ; sensorManager = (SensorManager) getContext().getSystemService(Context.SENSOR_SERVICE); sensor = sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER); gSenseView = new GSenseView(getContext()); params = new WindowManager.LayoutParams(); params.type = WindowManager.LayoutParams.TYPE_APPLICATION; params.flags = WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE; dm = getContext().getResources().getDisplayMetrics(); Drawable drawable = finder.getDrawable("browser_right_hover"); setBackgroundDrawable(drawable); params.height = drawable.getIntrinsicHeight(); params.width = drawable.getIntrinsicWidth(); params.alpha = 1.0f; params.format = PixelFormat.TRANSPARENT; params.gravity = Gravity.LEFT | Gravity.TOP; params.x = (int) (dm.widthPixels - 5 * dm.density - params.width); params.y = (int) (dm.heightPixels - 50 * dm.density - params.height); params.windowAnimations = finder.getStyleId("Anim_platform_myspace_fade"); } float startX; float startY; boolean dragable = false; @Override protected void onWindowVisibilityChanged(int visibility) { super.onWindowVisibilityChanged(visibility); if (cpuMHZ > 800) { if (visibility == View.VISIBLE) { // sensorManager.registerListener(this, sensor, // SensorManager.SENSOR_DELAY_UI); setClickable(true); } else { // sensorManager.unregisterListener(this, sensor); } } } @Override protected void onDetachedFromWindow() { super.onDetachedFromWindow(); if (gSenseView != null && isAddedSenseView) { windowManager.removeViewImmediate(gSenseView); } } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); } @Override public boolean onTouchEvent(MotionEvent event) { // 触摸点相对于屏幕左上角坐标 boolean isHandle = false; currentX = event.getRawX(); currentY = event.getRawY(); switch (event.getAction()) { case MotionEvent.ACTION_DOWN: startX = event.getX(); startY = event.getY(); break; case MotionEvent.ACTION_MOVE: if (!dragable) { final int touchSlop = ViewConfiguration.get(getContext()).getScaledTouchSlop(); if (Math.abs(event.getX() - startX) > touchSlop || Math.abs(event.getY() - startY) > touchSlop) { dragable = true; updatePosition(); isHandle = true; } } if (dragable) { updatePosition(); isHandle = true; } break; case MotionEvent.ACTION_UP: if (dragable) { updatePosition(); isHandle = true; } dragable = false; startX = startY = 0; break; } return isHandle ? isHandle : super.onTouchEvent(event); } // 更新浮动窗口位置参数 private void updatePosition() { // View的当前位置 params.x = (int) (currentX - startX); params.y = (int) (currentY - startY); windowManager.updateViewLayout(this, params); } private float x, y, z, last_x, last_y, last_z; private long lastUpdate; private static final int SHAKE_THRESHOLD = 2000; @Override public void onSensorChanged(SensorEvent event) { long curTime = System.currentTimeMillis(); // 每100毫秒检测一次 if ((curTime - lastUpdate) > 100) { long diffTime = (curTime - lastUpdate); lastUpdate = curTime; x = event.values[SensorManager.DATA_X]; y = event.values[SensorManager.DATA_Y]; z = event.values[SensorManager.DATA_Z]; float speed = Math.abs(x + y + z - last_x - last_y - last_z) / diffTime * 10000; if (speed > SHAKE_THRESHOLD) { // 检测到摇晃后执行的代码 setVisibility(View.GONE); setClickable(false); sensorManager.unregisterListener(this, sensor); if (!isAddedSenseView) { windowManager.addView(gSenseView, gSenseView.getLayoutParams()); isAddedSenseView = true; gSenseView.startSense(); gSenseView.addBallFallIntoCallback(new OnBallFallIntoCallback() { @Override public void onFallInto() { windowManager.removeViewImmediate(gSenseView); isAddedSenseView = false; if (listener != null) { listener.onGSBallFalled(); } } }); } } last_x = x; last_y = y; last_z = z; } } @Override public void onAccuracyChanged(Sensor sensor, int accuracy) { } public static interface OnGSBallFallListener { void onGSBallFalled(); } }