package com.limemobile.app.launcher.view; import android.content.Context; import android.content.Intent; import android.content.pm.PackageManager; import android.content.pm.ResolveInfo; import android.content.res.Resources; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Rect; import android.graphics.RectF; import android.graphics.drawable.BitmapDrawable; import android.net.Uri; import android.provider.MediaStore; import android.util.AttributeSet; import android.view.MotionEvent; import android.view.View; import android.view.animation.Animation; import android.view.animation.Animation.AnimationListener; import android.view.animation.AnimationUtils; import android.widget.FrameLayout; import android.widget.ImageView; import com.limemobile.app.launcher.util.IconCache; import com.limemobile.app.launcher.wp8.R; import java.util.ArrayList; import java.util.List; public class HTCSenseLockScreenView extends FrameLayout { private Context mContext; private ImageView mSenseUnlock; private ImageView mSensePanel; private ImageView mSenseLockCircle; private OnTriggeredListener mOnTriggeredListener; private BitmapDrawable mRingDrawable; private BitmapDrawable mRingAppDrawable; private BitmapDrawable mRingAppOnDrawable; private BitmapDrawable mRingUnlockDrawable; private BitmapDrawable mSenseAppBgDrawable; private float mDensity; private boolean mDragRing = false; private boolean mDragShortcut = false; private boolean mShortcutTriggered = false; private boolean mUnlockTriggered = false; private boolean mCalculateRect = false; private boolean mAnimationPlaying = false; private float mShortcutIconWidth; private float mShortcutIconHeight; private float mShortcutBasedHeight; private float mUnlockTriggeredHeight; private float mIconSpacing = 72.0f; // private Animation mUpAnim; // private Animation mDownAnim; private Animation mZoomEnterAnim; private Rect mRingBound = new Rect(0, 0, 0, 0); private ShortcutInfo mDraggingShortcut = null; private ArrayList<ShortcutInfo> mShortcuts = new ArrayList<ShortcutInfo>(); public static class ShortcutInfo { Rect bound; BitmapDrawable drawable; Intent intent; } public HTCSenseLockScreenView(Context context, AttributeSet attrs) { this(context, attrs, 0); } public HTCSenseLockScreenView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); mContext = context; } @Override protected void onFinishInflate() { mDensity = mContext.getResources().getDisplayMetrics().density; setBackgroundColor(Color.argb(230, 68, 68, 68)); mSenseUnlock = (ImageView) findViewById(R.id.sense_unlock); mSenseUnlock.setVisibility(View.GONE); mSensePanel = (ImageView) findViewById(R.id.sense_panel); mSenseLockCircle = (ImageView) findViewById(R.id.sense_lock_circle); mSenseLockCircle.setVisibility(View.INVISIBLE); loadBitmapDrawable(); resetRect(); mZoomEnterAnim = AnimationUtils.loadAnimation(mContext, R.anim.zoom_enter); mZoomEnterAnim.setFillAfter(false); // mUpAnim = new TranslateAnimation( // Animation.RELATIVE_TO_SELF, 0.0f, Animation.RELATIVE_TO_SELF, // 0.0f, Animation.RELATIVE_TO_SELF, 0.0f, // Animation.RELATIVE_TO_SELF, -0.5f); // mUpAnim.setDuration(400); // mUpAnim.setFillAfter(false); // mUpAnim.setRepeatCount(-1); // mUpAnim.setRepeatMode(Animation.REVERSE); // mUpAnim.setInterpolator(new AccelerateInterpolator()); // // mDownAnim = new TranslateAnimation( // Animation.RELATIVE_TO_SELF, 0.0f, Animation.RELATIVE_TO_SELF, // 0.0f, Animation.RELATIVE_TO_SELF, -0.5f, // Animation.RELATIVE_TO_SELF, 0.0f); // mDownAnim.setDuration(800); // mDownAnim.setFillAfter(false); // mDownAnim.setInterpolator(new DecelerateInterpolator()); super.onFinishInflate(); } @Override protected void onSizeChanged(int w, int h, int oldw, int oldh) { resetRect(); super.onSizeChanged(w, h, oldw, oldh); } @Override protected void onWindowVisibilityChanged(int visibility) { super.onWindowVisibilityChanged(visibility); } @Override protected void onDetachedFromWindow() { unloadBitmapDrawable(); super.onDetachedFromWindow(); } @Override public boolean onTouchEvent(MotionEvent event) { super.onTouchEvent(event); boolean shouldInvalidate = false; final int action = event.getAction(); final int x = (int) event.getX(); final int y = (int) event.getY(); final int width = getWidth(); final int height = getHeight(); switch (action) { case MotionEvent.ACTION_DOWN: if (!mShortcutTriggered && !mUnlockTriggered) { mDragShortcut = false; mDragRing = false; mDraggingShortcut = null; mShortcutTriggered = false; mUnlockTriggered = false; resetRect(); if (mRingBound.contains(x, y)) { mDragRing = true; replaceRing(x, y); shouldInvalidate = true; } else { for (ShortcutInfo info : mShortcuts) { if (info.bound.contains(x, y)) { mDraggingShortcut = info; mDragShortcut = true; shouldInvalidate = true; startDragShortcut(mDraggingShortcut); replaceShortcut(mDraggingShortcut, x, y); break; } } } } break; case MotionEvent.ACTION_MOVE: if (mDragRing) { shouldInvalidate = true; replaceRing(x, y); } if (mDragShortcut && mDraggingShortcut != null) { shouldInvalidate = true; replaceShortcut(mDraggingShortcut, x, y); } break; case MotionEvent.ACTION_UP: if (mDragShortcut && mDraggingShortcut != null && mRingBound.contains(x, y)) { mShortcutTriggered = true; shouldInvalidate = true; mDragShortcut = false; mDragRing = false; LayoutParams params = (LayoutParams) mSenseUnlock .getLayoutParams(); params.leftMargin = getLeft() + mRingBound.left; params.topMargin = getTop() + mRingBound.top; params.rightMargin = width - mRingBound.right; params.bottomMargin = height - mRingBound.bottom; triggered(mDraggingShortcut.intent); } else if (mDragRing && y < mUnlockTriggeredHeight) { mUnlockTriggered = true; shouldInvalidate = true; mDragShortcut = false; mDragRing = false; LayoutParams params = (LayoutParams) mSenseUnlock .getLayoutParams(); params.leftMargin = getLeft() + mRingBound.left; params.topMargin = getTop() + mRingBound.top; params.rightMargin = width - mRingBound.right; params.bottomMargin = height - mRingBound.bottom; triggered(null); } mDragShortcut = false; mDragRing = false; mDraggingShortcut = null; resetRect(); shouldInvalidate = true; break; case MotionEvent.ACTION_CANCEL: mDragShortcut = false; mDragRing = false; mShortcutTriggered = false; mUnlockTriggered = false; mDraggingShortcut = null; resetRect(); shouldInvalidate = true; break; } if (shouldInvalidate) invalidate(); return true; } @Override protected void dispatchDraw(Canvas canvas) { super.dispatchDraw(canvas); if (!mCalculateRect) { mCalculateRect = true; resetRect(); final int width = getWidth(); final int height = getHeight(); LayoutParams params = (LayoutParams) mSenseLockCircle.getLayoutParams(); Rect rect = new Rect(mRingBound); params.width = rect.width(); params.height = rect.height(); params.leftMargin = getLeft() + rect.left; params.topMargin = getTop() + rect.top; params.rightMargin = width - rect.right; params.bottomMargin = height - rect.bottom; mSenseLockCircle.setImageDrawable(mRingDrawable); } if (!mRingBound.isEmpty() && !mShortcutTriggered && !mUnlockTriggered && !mAnimationPlaying) { BitmapDrawable ringDrawable = null; if (!mDragRing && !mDragShortcut) { ringDrawable = mRingDrawable; } else if (mDragRing) { if (mRingBound.bottom < mUnlockTriggeredHeight) ringDrawable = mRingUnlockDrawable; else ringDrawable = mRingDrawable; } else if (mDragShortcut) { ringDrawable = mRingAppDrawable; for (ShortcutInfo info : mShortcuts) { if (info != null && mRingBound.contains(info.bound)) { ringDrawable = mRingAppOnDrawable; break; } } } if (ringDrawable != null) { ringDrawable.setBounds(mRingBound); ringDrawable.draw(canvas); if (mDragShortcut && mDraggingShortcut != null) { RectF bound = new RectF(); int width = mDraggingShortcut.bound.width(); int height = mDraggingShortcut.bound.height(); bound.left = mRingBound.centerX() - width / 2; bound.top = mRingBound.centerY() - height / 2; bound.right = bound.left + width; bound.bottom = bound.top + height; Rect src = new Rect(); src.left = 0; src.top = 0; src.right = (int) mShortcutIconWidth; src.bottom = (int) mShortcutIconHeight; canvas.drawBitmap(mDraggingShortcut.drawable.getBitmap(), src, bound, null); } } } if (!mDragRing) { for (ShortcutInfo info : mShortcuts) { if (info != null && info.drawable != null) { Rect rect = new Rect(info.bound); //rect.inset(-5, -5); //mSenseAppBgDrawable.setBounds(rect); //mSenseAppBgDrawable.draw(canvas); rect.bottom += rect.height() / 2; info.drawable.setBounds(rect); info.drawable.draw(canvas); } } } } private void triggered(final Intent intent) { if (mOnTriggeredListener != null) { mSenseUnlock.setVisibility(View.VISIBLE); mSenseUnlock.clearAnimation(); mZoomEnterAnim.setAnimationListener(new AnimationListener() { @Override public void onAnimationStart(Animation animation) { } @Override public void onAnimationRepeat(Animation animation) { } @Override public void onAnimationEnd(Animation animation) { mSenseUnlock.setVisibility(View.GONE); if (mShortcutTriggered) mOnTriggeredListener.OnShortcutTriggered(intent); if (mUnlockTriggered) mOnTriggeredListener.OnUnLockTriggered(); mShortcutTriggered = false; mUnlockTriggered = false; invalidate(); } }); mSenseUnlock.startAnimation(mZoomEnterAnim); } } private void startDragShortcut(ShortcutInfo info) { int width = mRingBound.width(); int height = mRingBound.height(); final int screenWidth = getWidth(); final int screenHeight = getHeight(); final int halfWidth = screenWidth / 2; mRingBound.left = halfWidth - width / 2; mRingBound.right = mRingBound.left + width; mRingBound.top = screenHeight - height * 3 / 4; mRingBound.bottom = mRingBound.top + height; int dx = info.bound.centerX() - mRingBound.centerX(); int dy = info.bound.centerY() - mRingBound.centerY(); mRingBound.offset(dx / 2, dy / 6); } private void replaceRing(int x, int y) { int width = mRingBound.width(); int height = mRingBound.height(); mRingBound.left = x - width / 2; mRingBound.right = mRingBound.left + width; mRingBound.top = y - height / 2; mRingBound.bottom = mRingBound.top + height; } private void replaceShortcut(ShortcutInfo info, int x, int y) { if (info != null) { int width = info.bound.width(); int height = info.bound.height(); info.bound.left = x - width / 2; info.bound.right = info.bound.left + width; info.bound.top = y - height / 2; info.bound.bottom = info.bound.top + height; } } private void resetRect() { final int width = getWidth(); final int height = getHeight(); final int halfWidth = width / 2; mShortcutBasedHeight = height - mRingAppDrawable.getBitmap().getHeight() / 2.0f - mSensePanel.getHeight(); mUnlockTriggeredHeight = mShortcutBasedHeight - mShortcutIconHeight; mIconSpacing = mShortcutIconWidth * 2 / 4; mRingBound.left = (int) (halfWidth - mRingAppDrawable.getBitmap().getWidth() / 2); mRingBound.top = (int) (height - mRingAppDrawable.getBitmap().getHeight() / 2); mRingBound.right = (int) (mRingBound.left + mRingAppDrawable.getBitmap().getWidth()); mRingBound.bottom = (int) (mRingBound.top + mRingAppDrawable.getBitmap().getHeight()); int length = mShortcuts.size(); assert (length % 2 == 0); for (int index = 0; index < length / 2; ++index) { ShortcutInfo info = mShortcuts.get(length / 2 - index - 1); info.bound.right = (int) (halfWidth - (index + 1) * mIconSpacing - index * mShortcutIconWidth); info.bound.left = (int) (info.bound.right - mShortcutIconWidth); info.bound.bottom = (int) mShortcutBasedHeight; info.bound.top = (int) (info.bound.bottom - mShortcutIconHeight); ShortcutInfo info2 = mShortcuts.get(length / 2 + index); info2.bound.left = (int) (halfWidth + (index + 1) * mIconSpacing + index * mShortcutIconWidth); info2.bound.right = (int) (info2.bound.left + mShortcutIconWidth); info2.bound.bottom = (int) mShortcutBasedHeight; info2.bound.top = (int) (info2.bound.bottom - mShortcutIconHeight); } } private void loadBitmapDrawable() { Resources res = mContext.getResources(); mRingDrawable = new BitmapDrawable( res.openRawResource(R.drawable.sense_ring)); mRingAppDrawable = new BitmapDrawable( res.openRawResource(R.drawable.sense_ring_appready)); mRingAppOnDrawable = new BitmapDrawable( res.openRawResource(R.drawable.sense_ring_appready_appon)); mRingUnlockDrawable = new BitmapDrawable( res.openRawResource(R.drawable.sense_ring_on_unlock)); mSenseAppBgDrawable = new BitmapDrawable( res.openRawResource(R.drawable.iphone_blank)); int alpha = 45; ShortcutInfo info = new ShortcutInfo(); info.bound = new Rect(); info.bound.setEmpty(); Bitmap bitmap = BitmapFactory.decodeStream(res.openRawResource(R.drawable.iphone_phone)); info.drawable = new BitmapDrawable(IconCache.createReflection(bitmap, 0, bitmap.getHeight() - bitmap.getHeight() / 2, 0, bitmap.getHeight() / 2, alpha)); info.intent = new Intent(Intent.ACTION_DIAL, null); mShortcutIconWidth = bitmap.getWidth(); mShortcutIconHeight = bitmap.getHeight(); bitmap.recycle(); mShortcuts.add(info); info = new ShortcutInfo(); info.bound = new Rect(); info.bound.setEmpty(); info.intent = new Intent(Intent.ACTION_VIEW, null); info.intent.setType("vnd.android-dir/mms-sms"); List<ResolveInfo> infos = mContext.getPackageManager().queryIntentActivities(info.intent, PackageManager.MATCH_DEFAULT_ONLY); if (infos != null && infos.size() > 0) { for (int index = 0; index < infos.size(); ++index) { ResolveInfo info2 = infos.get(index); if ((info2.activityInfo.applicationInfo.flags & android.content.pm.ApplicationInfo.FLAG_SYSTEM) == android.content.pm.ApplicationInfo.FLAG_SYSTEM) { info.intent = new Intent(Intent.ACTION_MAIN); info.intent.setPackage(info2.activityInfo.applicationInfo.packageName); info.intent.addCategory(Intent.CATEGORY_LAUNCHER); break; } } } bitmap = BitmapFactory.decodeStream(res.openRawResource(R.drawable.iphone_imessage)); info.drawable = new BitmapDrawable(IconCache.createReflection(bitmap, 0, bitmap.getHeight() - bitmap.getHeight() / 2, 0, bitmap.getHeight() / 2, alpha)); bitmap.recycle(); mShortcuts.add(info); info = new ShortcutInfo(); info.bound = new Rect(); info.bound.setEmpty(); info.intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); bitmap = BitmapFactory.decodeStream(res.openRawResource(R.drawable.iphone_camera)); info.drawable = new BitmapDrawable(IconCache.createReflection(bitmap, 0, bitmap.getHeight() - bitmap.getHeight() / 2, 0, bitmap.getHeight() / 2, alpha)); bitmap.recycle(); mShortcuts.add(info); info = new ShortcutInfo(); info.bound = new Rect(); info.bound.setEmpty(); info.intent = new Intent(Intent.ACTION_VIEW, Uri.parse(getContext().getString(R.string.default_browser_url))); bitmap = BitmapFactory.decodeStream(res.openRawResource(R.drawable.iphone_safari)); info.drawable = new BitmapDrawable(IconCache.createReflection(bitmap, 0, bitmap.getHeight() - bitmap.getHeight() / 2, 0, bitmap.getHeight() / 2, alpha)); bitmap.recycle(); mShortcuts.add(info); } private void unloadBitmapDrawable() { if (mSenseLockCircle != null) mSenseLockCircle.setImageDrawable(null); if (mRingDrawable != null) { mRingDrawable.setCallback(null); if (mRingDrawable.getBitmap() != null && !mRingDrawable.getBitmap().isRecycled()) mRingDrawable.getBitmap().recycle(); } if (mRingAppDrawable != null) { mRingAppDrawable.setCallback(null); if (mRingAppDrawable.getBitmap() != null && !mRingAppDrawable.getBitmap().isRecycled()) mRingAppDrawable.getBitmap().recycle(); } if (mRingAppOnDrawable != null) { mRingAppOnDrawable.setCallback(null); if (mRingAppOnDrawable.getBitmap() != null && !mRingAppOnDrawable.getBitmap().isRecycled()) mRingAppOnDrawable.getBitmap().recycle(); } if (mRingUnlockDrawable != null) { mRingUnlockDrawable.setCallback(null); if (mRingUnlockDrawable.getBitmap() != null && !mRingUnlockDrawable.getBitmap().isRecycled()) mRingUnlockDrawable.getBitmap().recycle(); } if (mSenseAppBgDrawable != null) { mSenseAppBgDrawable.setCallback(null); if (mSenseAppBgDrawable.getBitmap() != null && !mSenseAppBgDrawable.getBitmap().isRecycled()) mSenseAppBgDrawable.getBitmap().recycle(); } for (ShortcutInfo info : mShortcuts) { if (info != null && info.drawable != null) { info.drawable.setCallback(null); if (info.drawable.getBitmap() != null && !info.drawable.getBitmap().isRecycled()) info.drawable.getBitmap().recycle(); } } mShortcuts.clear(); } public OnTriggeredListener getOnTriggeredListener() { return mOnTriggeredListener; } public void setOnTriggeredListener(OnTriggeredListener l) { this.mOnTriggeredListener = l; } // public void setLayoutAnim_slidedown(ViewGroup panel, Context ctx) { // // AnimationSet set = new AnimationSet(true); // // Animation animation = new TranslateAnimation( // Animation.RELATIVE_TO_SELF, 0.0f, Animation.RELATIVE_TO_SELF, // 0.0f, Animation.RELATIVE_TO_SELF, -1.0f, // Animation.RELATIVE_TO_SELF, 0.0f); // animation.setDuration(800); // animation.setAnimationListener(new AnimationListener() { // // @Override // public void onAnimationStart(Animation animation) { // // TODO Auto-generated method stub // // MapContacts.this.mapviewgroup.setVisibility(View.VISIBLE); // // } // // @Override // public void onAnimationRepeat(Animation animation) { // // TODO Auto-generated method stub // // } // // @Override // public void onAnimationEnd(Animation animation) { // // // TODO Auto-generated method stub // // } // }); // set.addAnimation(animation); // // LayoutAnimationController controller = new LayoutAnimationController( // set, 0.25f); // panel.setLayoutAnimation(controller); // // } // // public void setLayoutAnim_slideup(ViewGroup panel, Context ctx) { // // AnimationSet set = new AnimationSet(true); // // /* // * Animation animation = new AlphaAnimation(1.0f, 0.0f); // * animation.setDuration(200); set.addAnimation(animation); // */ // // Animation animation = new TranslateAnimation( // Animation.RELATIVE_TO_SELF, 0.0f, Animation.RELATIVE_TO_SELF, // 0.0f, Animation.RELATIVE_TO_SELF, 0.0f, // Animation.RELATIVE_TO_SELF, -1.0f); // animation.setDuration(800); // animation.setAnimationListener(new AnimationListener() { // // @Override // public void onAnimationStart(Animation animation) { // // TODO Auto-generated method stub // // } // // @Override // public void onAnimationRepeat(Animation animation) { // // TODO Auto-generated method stub // // } // // @Override // public void onAnimationEnd(Animation animation) { // // MapContacts.this.mapviewgroup.setVisibility(View.INVISIBLE); // // TODO Auto-generated method stub // // } // }); // set.addAnimation(animation); // // LayoutAnimationController controller = new LayoutAnimationController( // set, 0.25f); // panel.setLayoutAnimation(controller); // // } public interface OnTriggeredListener { void OnUnLockTriggered(); void OnShortcutTriggered(Intent intent); } }