From c99181dc9fe9c49f3806b6cc135776e7973c0ee2 Mon Sep 17 00:00:00 2001 From: zzz40500 Date: Wed, 4 Feb 2015 13:36:42 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E6=94=B9=20heads-up=20=E4=B8=8A?= =?UTF-8?q?=E7=9A=84=E5=9B=BE=E6=A0=87=E4=B8=BA=E5=9C=86=E5=BD=A2,?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 修改 heads-up 上的图标为圆形,在5.0上使用自身的 notification --- .idea/misc.xml | 16 - .../java/com/mingle/headsupdemo/Distance.java | 42 --- .../com/mingle/headsupdemo/MainActivity.java | 18 +- library/build.gradle | 1 + library/library.iml | 1 + .../java/com/mingle/headsUp/FloatView.java | 5 +- .../main/java/com/mingle/headsUp/HeadsUp.java | 26 +- .../com/mingle/headsUp/HeadsUpManager.java | 17 +- .../headsUp/widget/CircleImageView.java | 318 ++++++++++++++++++ library/src/main/res/layout/notification.xml | 7 +- .../res/values/circle_imageview_attrs.xml | 7 + 11 files changed, 385 insertions(+), 73 deletions(-) delete mode 100644 app/src/main/java/com/mingle/headsupdemo/Distance.java create mode 100644 library/src/main/java/com/mingle/headsUp/widget/CircleImageView.java create mode 100755 library/src/main/res/values/circle_imageview_attrs.xml diff --git a/.idea/misc.xml b/.idea/misc.xml index fdbc761..7063e7b 100644 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -107,21 +107,5 @@ 5050 - - - - - 1.7 - - - - - - - diff --git a/app/src/main/java/com/mingle/headsupdemo/Distance.java b/app/src/main/java/com/mingle/headsupdemo/Distance.java deleted file mode 100644 index 512b260..0000000 --- a/app/src/main/java/com/mingle/headsupdemo/Distance.java +++ /dev/null @@ -1,42 +0,0 @@ -package com.mingle.headsupdemo; - -import android.content.Context; -import android.hardware.SensorManager; -import android.view.ViewConfiguration; - -/** - * Created by zzz40500 on 15/1/29. - */ -public class Distance { - private float mFlingFriction = ViewConfiguration.getScrollFriction(); - - private static float DECELERATION_RATE = (float) (Math.log(0.78) / Math.log(0.9)); - private static final float INFLEXION = 0.35f; - private float mPhysicalCoeff; - - - public Distance(Context context){ - - final float ppi = context.getResources().getDisplayMetrics().density * 160.0f; - mPhysicalCoeff = SensorManager.GRAVITY_EARTH // g (m/s^2) - * 39.37f // inch/meter - * ppi - * 0.84f; // look and feel tuning - } - private double getSplineFlingDistance(int velocity) { - final double l = getSplineDeceleration(velocity); - final double decelMinusOne = DECELERATION_RATE - 1.0; - return mFlingFriction * mPhysicalCoeff * Math.exp(DECELERATION_RATE / decelMinusOne * l); - } - - private double getSplineDeceleration(int velocity) { - return Math.log(INFLEXION * Math.abs(velocity) / (mFlingFriction * mPhysicalCoeff)); - } - - /* Returns the duration, expressed in milliseconds */ - private int getSplineFlingDuration(int velocity) { - final double l = getSplineDeceleration(velocity); - final double decelMinusOne = DECELERATION_RATE - 1.0; - return (int) (1000.0 * Math.exp(l / decelMinusOne)); - } -} diff --git a/app/src/main/java/com/mingle/headsupdemo/MainActivity.java b/app/src/main/java/com/mingle/headsupdemo/MainActivity.java index 35f2eb4..ca7f2bf 100644 --- a/app/src/main/java/com/mingle/headsupdemo/MainActivity.java +++ b/app/src/main/java/com/mingle/headsupdemo/MainActivity.java @@ -1,14 +1,20 @@ package com.mingle.headsupdemo; import android.app.Notification; +import android.app.NotificationManager; import android.app.PendingIntent; +import android.content.Context; import android.content.Intent; import android.net.Uri; import android.os.Bundle; +import android.support.v4.app.NotificationCompat; import android.support.v7.app.ActionBarActivity; import android.view.Menu; import android.view.MenuItem; import android.view.View; +import android.view.Window; +import android.view.WindowManager; +import android.widget.RemoteViews; import android.widget.ScrollView; import com.mingle.headsUp.HeadsUp; @@ -21,12 +27,16 @@ public class MainActivity extends ActionBarActivity { private int code=1; + private Context context; + @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); + context=this; + findViewById(R.id.l0).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { @@ -41,7 +51,7 @@ public void onClick(View v) { .setSmallIcon(R.drawable.icon) //2.3 一定要设置这个参数,负责会报错 .setContentIntent(pendingIntent) - + .setFullScreenIntent(pendingIntent,false) .setContentText("你有新的消息"); HeadsUp headsUp = builder.buildHeadUp(); @@ -63,8 +73,9 @@ public void onClick(View v) { //要显示通知栏通知,这个一定要设置 .setSmallIcon(R.drawable.icon) .setContentText("你有新的消息") - //2.3 一定要设置这个参数,负责会报错 + //2.3 一定要设置这个参数,负责会报错 .setContentIntent(pendingIntent) + .setFullScreenIntent(pendingIntent, false) //设置是否显示 action 按键 .setUsesChronometer(true) .addAction(R.drawable.ic_cloud_queue_black_24dp, "查看", pendingIntent); @@ -117,6 +128,9 @@ public void onClick(View v) { HeadsUpManager.getInstant(MainActivity.this).cancelAll(); + + + } }); diff --git a/library/build.gradle b/library/build.gradle index 7b56c8a..1d42827 100755 --- a/library/build.gradle +++ b/library/build.gradle @@ -21,4 +21,5 @@ dependencies { compile 'com.nineoldandroids:library:2.4.0' compile 'com.android.support:support-v4:21.0.3' compile 'com.android.support:cardview-v7:21.0.3' + compile 'com.joooonho:selectableroundedimageview:1.0.0' } diff --git a/library/library.iml b/library/library.iml index d615107..21b52f6 100644 --- a/library/library.iml +++ b/library/library.iml @@ -84,6 +84,7 @@ + diff --git a/library/src/main/java/com/mingle/headsUp/FloatView.java b/library/src/main/java/com/mingle/headsUp/FloatView.java index 5d0de24..f4c93cc 100755 --- a/library/src/main/java/com/mingle/headsUp/FloatView.java +++ b/library/src/main/java/com/mingle/headsUp/FloatView.java @@ -160,7 +160,6 @@ public boolean onTouchEvent(MotionEvent event) { }else{ toX= (int) (preLeft-Math.abs(dis)); } - Log.e("toX"," "+toX); if (toX <= -validWidth) { float preAlpha=1-Math.abs(preLeft)/validWidth; preAlpha=preAlpha>=0?preAlpha:0; @@ -260,7 +259,9 @@ public void setNotification(final HeadsUp headsUp) { @Override public void handleMessage(Message msg) { super.handleMessage(msg); - HeadsUpManager.getInstant(getContext()).silencerNotify(headsUp); + if(headsUp.isActivateStatusBar()) { + HeadsUpManager.getInstant(getContext()).silencerNotify(headsUp); + } HeadsUpManager.getInstant(getContext()).animDismiss(headsUp); } }; diff --git a/library/src/main/java/com/mingle/headsUp/HeadsUp.java b/library/src/main/java/com/mingle/headsUp/HeadsUp.java index 5d34dbf..be5eff6 100755 --- a/library/src/main/java/com/mingle/headsUp/HeadsUp.java +++ b/library/src/main/java/com/mingle/headsUp/HeadsUp.java @@ -23,7 +23,7 @@ public class HeadsUp { /** * 出现时间 单位是 second */ - private long duration= 8; + private long duration= 9; /** * */ @@ -33,6 +33,10 @@ public class HeadsUp { private boolean isSticky=false; + + private boolean activateStatusBar=true; + + /** * */ @@ -59,7 +63,6 @@ private HeadsUp(Context context) { public static class Builder extends NotificationCompat.Builder { - private Context context; private List actions=new ArrayList(); private HeadsUp headsUp; @@ -97,6 +100,10 @@ public Builder setSmallIcon(int icon) { // super.setSmallIcon(icon); return this; } + protected Builder setIcon(int icon){ + super.setSmallIcon(icon); + return this; + } @@ -126,7 +133,7 @@ public HeadsUp buildHeadUp(){ return headsUp; } - private Notification silencerNotifcation(){ + private Notification silencerNotification(){ super.setSmallIcon(headsUp.getIcon()); setDefaults(0); return this.build(); @@ -462,12 +469,12 @@ protected void setExpand(boolean isExpand) { } protected Notification getSilencerNotification() { - return getBuilder().silencerNotifcation(); + return getBuilder().silencerNotification(); } - private Builder getBuilder() { + protected Builder getBuilder() { return builder; } @@ -483,4 +490,13 @@ public boolean isSticky() { public void setSticky(boolean isSticky) { this.isSticky = isSticky; } + + + protected boolean isActivateStatusBar() { + return activateStatusBar; + } + + public void setActivateStatusBar(boolean activateStatusBar) { + this.activateStatusBar = activateStatusBar; + } } diff --git a/library/src/main/java/com/mingle/headsUp/HeadsUpManager.java b/library/src/main/java/com/mingle/headsUp/HeadsUpManager.java index f557e3b..1ab3cee 100755 --- a/library/src/main/java/com/mingle/headsUp/HeadsUpManager.java +++ b/library/src/main/java/com/mingle/headsUp/HeadsUpManager.java @@ -2,6 +2,7 @@ import android.app.NotificationManager; import android.content.Context; +import android.os.Build; import android.view.Gravity; import android.view.WindowManager; @@ -86,8 +87,17 @@ private synchronized void poll() { if (!msgQueue.isEmpty()) { HeadsUp headsUp = msgQueue.poll(); map.remove(headsUp.getCode()); - isPolling = true; - show(headsUp); + + + if ( Build.VERSION.SDK_INT < 21 || headsUp.getCustomView() != null || !headsUp.isActivateStatusBar()){ + isPolling = true; + show(headsUp); + }else { + //当 系统是 lollipop 以上,并且没有自定义布局以后,调用系统自己的 notification + isPolling = false; + notificationManager.notify(headsUp.getCode(),headsUp.getBuilder().setIcon(headsUp.getIcon()).build()); + + } } else { isPolling = false; } @@ -97,7 +107,6 @@ private synchronized void poll() { private void show(HeadsUp headsUp) { floatView = new FloatView(context, 20); - WindowManager.LayoutParams params = FloatView.winParams; params.flags = WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE|WindowManager.LayoutParams.FLAG_FULLSCREEN @@ -115,7 +124,7 @@ private void show(HeadsUp headsUp) { a.setDuration(600); a.start(); floatView.setNotification(headsUp); - if(headsUp.getNotification()!=null){ + if(headsUp.getNotification()!=null ){ notificationManager.notify(headsUp.getCode(), headsUp.getNotification()); } diff --git a/library/src/main/java/com/mingle/headsUp/widget/CircleImageView.java b/library/src/main/java/com/mingle/headsUp/widget/CircleImageView.java new file mode 100644 index 0000000..1a04969 --- /dev/null +++ b/library/src/main/java/com/mingle/headsUp/widget/CircleImageView.java @@ -0,0 +1,318 @@ +package com.mingle.headsUp.widget; + +import android.content.Context; +import android.content.res.ColorStateList; +import android.content.res.TypedArray; +import android.graphics.Bitmap; +import android.graphics.BitmapShader; +import android.graphics.Canvas; +import android.graphics.Color; +import android.graphics.ColorFilter; +import android.graphics.Matrix; +import android.graphics.Paint; +import android.graphics.RectF; +import android.graphics.Shader; +import android.graphics.drawable.BitmapDrawable; +import android.graphics.drawable.ColorDrawable; +import android.graphics.drawable.Drawable; +import android.net.Uri; +import android.util.AttributeSet; +import android.util.Log; +import android.view.MotionEvent; +import android.widget.ImageView; + +import com.example.administrator.ll.R; + + +public class CircleImageView extends ImageView { + + private static final ScaleType SCALE_TYPE = ScaleType.CENTER_CROP; + + private static final Bitmap.Config BITMAP_CONFIG = Bitmap.Config.ARGB_8888; + private static final int COLORDRAWABLE_DIMENSION = 2; + + private static final int DEFAULT_BORDER_WIDTH = 2; + private static final int DEFAULT_BORDER_COLOR = Color.BLACK; + + private final RectF mDrawableRect = new RectF(); + private final RectF mBorderRect = new RectF(); + + private final Matrix mShaderMatrix = new Matrix(); + private final Paint mBitmapPaint = new Paint(); + private final Paint mBorderPaint = new Paint(); + + private ColorStateList mBorderColorStateList; + private int mBorderColor; + private int mBorderWidth = DEFAULT_BORDER_WIDTH; + + private Bitmap mBitmap; + private BitmapShader mBitmapShader; + private int mBitmapWidth; + private int mBitmapHeight; + + private float mDrawableRadius; + private float mBorderRadius; + + private ColorFilter mColorFilter; + + private boolean mReady; + private boolean mSetupPending; + + public CircleImageView(Context context) { + super(context); + + init(); + } + + public CircleImageView(Context context, AttributeSet attrs) { + this(context, attrs, 0); + } + + private int paddingTop,paddingLeft,paddingRight,paddingBottom; + + public CircleImageView(Context context, AttributeSet attrs, int defStyle) { + super(context, attrs, defStyle); + + TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.CircleImageView, defStyle, 0); + + mBorderWidth = a.getDimensionPixelSize(R.styleable.CircleImageView_border_width, DEFAULT_BORDER_WIDTH); + mBorderColorStateList = a.getColorStateList(R.styleable.CircleImageView_border_color); + if(mBorderColorStateList!=null) { + mBorderColor = mBorderColorStateList.getColorForState(getDrawableState(), Color.WHITE); + }else{ + mBorderColor=Color.WHITE; + } + a.recycle(); + + paddingTop=getPaddingTop(); + paddingLeft=getPaddingLeft(); + paddingRight=getPaddingRight(); + paddingBottom=getPaddingBottom(); + + + init(); + } + + private void init() { + super.setScaleType(SCALE_TYPE); + mReady = true; + + if (mSetupPending) { + setup(); + mSetupPending = false; + } + } + + @Override + public ScaleType getScaleType() { + return SCALE_TYPE; + } + + @Override + public void setScaleType(ScaleType scaleType) { + if (scaleType != SCALE_TYPE) { + throw new IllegalArgumentException(String.format("ScaleType %s not supported.", scaleType)); + } + } + + @Override + public void setAdjustViewBounds(boolean adjustViewBounds) { + if (adjustViewBounds) { + throw new IllegalArgumentException("adjustViewBounds not supported."); + } + } + + @Override + protected void onDraw(Canvas canvas) { + if (getDrawable() == null) { + return; + } + canvas.drawCircle(paddingLeft+(getWidth()-paddingRight-paddingLeft) / 2, paddingTop+(getHeight()-paddingTop-paddingBottom )/ 2, mDrawableRadius, mBitmapPaint); + if (mBorderWidth != 0) { + + mBorderPaint.setColor(mBorderColor); + canvas.drawCircle( + paddingLeft+(getWidth()-paddingRight-paddingLeft) / 2, paddingTop+(getHeight()-paddingTop-paddingBottom )/ 2 + , mBorderRadius, mBorderPaint); + } + } + + @Override + public boolean onTouchEvent(MotionEvent event) { + + + if(mBorderColorStateList ==null || !isClickable()){ + return super.onTouchEvent(event); + } + + switch (event.getAction()){ + case MotionEvent.ACTION_UP: + case MotionEvent.ACTION_CANCEL: + mBorderColor=mBorderColorStateList.getDefaultColor(); + break; + + default: + mBorderColor = mBorderColorStateList.getColorForState(getDrawableState(), Color.WHITE); + + break; + } + invalidate(); + return super.onTouchEvent(event); + } + + @Override + protected void onSizeChanged(int w, int h, int oldw, int oldh) { + super.onSizeChanged(w, h, oldw, oldh); + setup(); + } + + public int getBorderColor() { + return mBorderColor; + } + + public void setBorderColor(int borderColor) { + if (borderColor == mBorderColor) { + return; + } + + mBorderColor = borderColor; + mBorderPaint.setColor(mBorderColor); + invalidate(); + } + + public int getBorderWidth() { + return mBorderWidth; + } + + public void setBorderWidth(int borderWidth) { + if (borderWidth == mBorderWidth) { + return; + } + + mBorderWidth = borderWidth; + setup(); + } + + @Override + public void setImageBitmap(Bitmap bm) { + super.setImageBitmap(bm); + mBitmap = bm; + setup(); + } + + @Override + public void setImageDrawable(Drawable drawable) { + super.setImageDrawable(drawable); + mBitmap = getBitmapFromDrawable(drawable); + setup(); + } + + @Override + public void setImageResource(int resId) { + super.setImageResource(resId); + mBitmap = getBitmapFromDrawable(getDrawable()); + setup(); + } + + @Override + public void setImageURI(Uri uri) { + super.setImageURI(uri); + mBitmap = getBitmapFromDrawable(getDrawable()); + setup(); + } + + @Override + public void setColorFilter(ColorFilter cf) { + if (cf == mColorFilter) { + return; + } + + mColorFilter = cf; + mBitmapPaint.setColorFilter(mColorFilter); + invalidate(); + } + + private Bitmap getBitmapFromDrawable(Drawable drawable) { + if (drawable == null) { + return null; + } + + if (drawable instanceof BitmapDrawable) { + return ((BitmapDrawable) drawable).getBitmap(); + } + + try { + Bitmap bitmap; + + if (drawable instanceof ColorDrawable) { + bitmap = Bitmap.createBitmap(COLORDRAWABLE_DIMENSION, COLORDRAWABLE_DIMENSION, BITMAP_CONFIG); + } else { + bitmap = Bitmap.createBitmap(drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight(), BITMAP_CONFIG); + } + + Canvas canvas = new Canvas(bitmap); + drawable.setBounds(paddingLeft, paddingTop, canvas.getWidth()-paddingRight, canvas.getHeight()-paddingBottom); + drawable.draw(canvas); + return bitmap; + } catch (OutOfMemoryError e) { + return null; + } + } + + private void setup() { + if (!mReady) { + mSetupPending = true; + return; + } + + if (mBitmap == null) { + return; + } + + mBitmapShader = new BitmapShader(mBitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP); + + mBitmapPaint.setAntiAlias(true); + mBitmapPaint.setShader(mBitmapShader); + + mBorderPaint.setStyle(Paint.Style.STROKE); + mBorderPaint.setAntiAlias(true); + + mBorderPaint.setStrokeWidth(mBorderWidth); + + mBitmapHeight = mBitmap.getHeight(); + mBitmapWidth = mBitmap.getWidth(); + + mBorderRect.set(paddingLeft, paddingTop, getWidth()-paddingRight, getHeight()-paddingBottom); + mBorderRadius = Math.min((mBorderRect.height()-mBorderWidth) / 2,( mBorderRect.width()-mBorderWidth) / 2); + + + mDrawableRect.set(mBorderWidth+paddingLeft, mBorderWidth+paddingTop, getWidth()-paddingRight - mBorderWidth, getHeight()-paddingBottom - mBorderWidth); + mDrawableRadius = Math.min(mDrawableRect.height() / 2, mDrawableRect.width() / 2); + + Log.e("mDrawableRadius", mDrawableRadius + ""); + updateShaderMatrix(); + invalidate(); + } + + private void updateShaderMatrix() { + float scale; + float dx = 0; + float dy = 0; + + mShaderMatrix.set(null); + + if (mBitmapWidth * mDrawableRect.height() > mDrawableRect.width() * mBitmapHeight) { + scale = mDrawableRect.height() / (float) mBitmapHeight; + dx = (mDrawableRect.width() - mBitmapWidth * scale) * 0.5f; + } else { + scale = mDrawableRect.width() / (float) mBitmapWidth; + dy = (mDrawableRect.height() - mBitmapHeight * scale) * 0.5f; + } + + mShaderMatrix.setScale(scale, scale); + mShaderMatrix.postTranslate((int) (dx + 0.5f) +paddingLeft+ mBorderWidth, (int) (dy + 0.5f) + paddingTop+mBorderWidth); + + mBitmapShader.setLocalMatrix(mShaderMatrix); + } + +} \ No newline at end of file diff --git a/library/src/main/res/layout/notification.xml b/library/src/main/res/layout/notification.xml index 43f1e0b..5d52e28 100755 --- a/library/src/main/res/layout/notification.xml +++ b/library/src/main/res/layout/notification.xml @@ -4,11 +4,14 @@ android:layout_height="fill_parent"> - + + + + + + \ No newline at end of file