初始化
This commit is contained in:
@@ -0,0 +1,14 @@
|
||||
apply plugin: 'com.android.library'
|
||||
|
||||
android {
|
||||
compileSdkVersion rootProject.ext.compileSdkVersion
|
||||
buildToolsVersion rootProject.ext.buildToolsVersion
|
||||
|
||||
defaultConfig {
|
||||
minSdkVersion rootProject.ext.minSdkVersion
|
||||
targetSdkVersion rootProject.ext.targetSdkVersion
|
||||
}
|
||||
}
|
||||
|
||||
// gradle uploadArchives
|
||||
//apply from: 'https://raw.githubusercontent.com/bingoogolapple/PublishAar/master/central-publish.gradle'
|
||||
@@ -0,0 +1,3 @@
|
||||
PUBLISH_AAR_ARTIFACT_ID=bga-badgeview
|
||||
PUBLISH_AAR_DESCRIPTION=Android BadgeView Library
|
||||
PUBLISH_AAR_GITHUB_REPOSITORIES_NAME=BGABadgeView-Android
|
||||
@@ -0,0 +1,3 @@
|
||||
<manifest package="cn.bingoogolapple.badgeview"/>
|
||||
<!--
|
||||
ss-->
|
||||
@@ -0,0 +1,98 @@
|
||||
/**
|
||||
* Copyright 2015 bingoogolapple
|
||||
* <p/>
|
||||
* 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
|
||||
* <p/>
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* <p/>
|
||||
* 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 cn.bingoogolapple.badgeview;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.Canvas;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.MotionEvent;
|
||||
import android.widget.FrameLayout;
|
||||
|
||||
/**
|
||||
* 作者:王浩 邮件:bingoogolapple@gmail.com
|
||||
* 创建时间:15/7/7 14:07
|
||||
* 描述:
|
||||
*/
|
||||
public class BGABadgeFrameLayout extends FrameLayout implements BGABadgeable {
|
||||
private BGABadgeViewHelper mBadgeViewHeler;
|
||||
|
||||
public BGABadgeFrameLayout(Context context) {
|
||||
this(context, null);
|
||||
}
|
||||
|
||||
public BGABadgeFrameLayout(Context context, AttributeSet attrs) {
|
||||
this(context, attrs, 0);
|
||||
}
|
||||
|
||||
public BGABadgeFrameLayout(Context context, AttributeSet attrs, int defStyleAttr) {
|
||||
super(context, attrs, defStyleAttr);
|
||||
mBadgeViewHeler = new BGABadgeViewHelper(this, context, attrs, BGABadgeViewHelper.BadgeGravity.RightCenter);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean onTouchEvent(MotionEvent event) {
|
||||
return mBadgeViewHeler.onTouchEvent(event);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean callSuperOnTouchEvent(MotionEvent event) {
|
||||
return super.onTouchEvent(event);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void dispatchDraw(Canvas canvas) {
|
||||
super.dispatchDraw(canvas);
|
||||
mBadgeViewHeler.drawBadge(canvas);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void showCirclePointBadge() {
|
||||
mBadgeViewHeler.showCirclePointBadge();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void showTextBadge(String badgeText) {
|
||||
mBadgeViewHeler.showTextBadge(badgeText);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void hiddenBadge() {
|
||||
mBadgeViewHeler.hiddenBadge();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void showDrawableBadge(Bitmap bitmap) {
|
||||
mBadgeViewHeler.showDrawable(bitmap);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setDragDismissDelegage(BGADragDismissDelegate delegate) {
|
||||
mBadgeViewHeler.setDragDismissDelegage(delegate);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isShowBadge() {
|
||||
return mBadgeViewHeler.isShowBadge();
|
||||
}
|
||||
|
||||
@Override
|
||||
public BGABadgeViewHelper getBadgeViewHelper() {
|
||||
return mBadgeViewHeler;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,97 @@
|
||||
/**
|
||||
* Copyright 2015 bingoogolapple
|
||||
*
|
||||
* 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 cn.bingoogolapple.badgeview;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.Canvas;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.MotionEvent;
|
||||
import android.widget.ImageView;
|
||||
|
||||
/**
|
||||
* 作者:王浩 邮件:bingoogolapple@gmail.com
|
||||
* 创建时间:15/7/6 下午3:04
|
||||
* 描述:
|
||||
*/
|
||||
public class BGABadgeImageView extends ImageView implements BGABadgeable {
|
||||
private BGABadgeViewHelper mBadgeViewHeler;
|
||||
|
||||
public BGABadgeImageView(Context context) {
|
||||
this(context, null);
|
||||
}
|
||||
|
||||
public BGABadgeImageView(Context context, AttributeSet attrs) {
|
||||
this(context, attrs, 0);
|
||||
}
|
||||
|
||||
public BGABadgeImageView(Context context, AttributeSet attrs, int defStyleAttr) {
|
||||
super(context, attrs, defStyleAttr);
|
||||
mBadgeViewHeler = new BGABadgeViewHelper(this, context, attrs, BGABadgeViewHelper.BadgeGravity.RightTop);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onTouchEvent(MotionEvent event) {
|
||||
return mBadgeViewHeler.onTouchEvent(event);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean callSuperOnTouchEvent(MotionEvent event) {
|
||||
return super.onTouchEvent(event);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDraw(Canvas canvas) {
|
||||
super.onDraw(canvas);
|
||||
mBadgeViewHeler.drawBadge(canvas);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void showCirclePointBadge() {
|
||||
mBadgeViewHeler.showCirclePointBadge();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void showTextBadge(String badgeText) {
|
||||
mBadgeViewHeler.showTextBadge(badgeText);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void hiddenBadge() {
|
||||
mBadgeViewHeler.hiddenBadge();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void showDrawableBadge(Bitmap bitmap) {
|
||||
mBadgeViewHeler.showDrawable(bitmap);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setDragDismissDelegage(BGADragDismissDelegate delegate) {
|
||||
mBadgeViewHeler.setDragDismissDelegage(delegate);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isShowBadge() {
|
||||
return mBadgeViewHeler.isShowBadge();
|
||||
}
|
||||
|
||||
@Override
|
||||
public BGABadgeViewHelper getBadgeViewHelper() {
|
||||
return mBadgeViewHeler;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,93 @@
|
||||
/**
|
||||
* Copyright 2015 bingoogolapple
|
||||
* <p/>
|
||||
* 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
|
||||
* <p/>
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* <p/>
|
||||
* 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 cn.bingoogolapple.badgeview;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.Canvas;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.MotionEvent;
|
||||
import android.widget.LinearLayout;
|
||||
|
||||
/**
|
||||
* 作者:王浩 邮件:bingoogolapple@gmail.com
|
||||
* 创建时间:15/7/7 14:07
|
||||
* 描述:
|
||||
*/
|
||||
public class BGABadgeLinearLayout extends LinearLayout implements BGABadgeable {
|
||||
private BGABadgeViewHelper mBadgeViewHeler;
|
||||
|
||||
public BGABadgeLinearLayout(Context context) {
|
||||
this(context, null);
|
||||
}
|
||||
|
||||
public BGABadgeLinearLayout(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
mBadgeViewHeler = new BGABadgeViewHelper(this, context, attrs, BGABadgeViewHelper.BadgeGravity.RightCenter);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onTouchEvent(MotionEvent event) {
|
||||
return mBadgeViewHeler.onTouchEvent(event);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean callSuperOnTouchEvent(MotionEvent event) {
|
||||
return super.onTouchEvent(event);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void dispatchDraw(Canvas canvas) {
|
||||
super.dispatchDraw(canvas);
|
||||
mBadgeViewHeler.drawBadge(canvas);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void showCirclePointBadge() {
|
||||
mBadgeViewHeler.showCirclePointBadge();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void showTextBadge(String badgeText) {
|
||||
mBadgeViewHeler.showTextBadge(badgeText);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void hiddenBadge() {
|
||||
mBadgeViewHeler.hiddenBadge();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void showDrawableBadge(Bitmap bitmap) {
|
||||
mBadgeViewHeler.showDrawable(bitmap);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setDragDismissDelegage(BGADragDismissDelegate delegate) {
|
||||
mBadgeViewHeler.setDragDismissDelegage(delegate);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isShowBadge() {
|
||||
return mBadgeViewHeler.isShowBadge();
|
||||
}
|
||||
|
||||
@Override
|
||||
public BGABadgeViewHelper getBadgeViewHelper() {
|
||||
return mBadgeViewHeler;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,97 @@
|
||||
/**
|
||||
* Copyright 2015 bingoogolapple
|
||||
*
|
||||
* 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 cn.bingoogolapple.badgeview;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.Canvas;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.MotionEvent;
|
||||
import android.widget.RadioButton;
|
||||
|
||||
/**
|
||||
* 作者:王浩 邮件:bingoogolapple@gmail.com
|
||||
* 创建时间:15/7/6 下午3:04
|
||||
* 描述:
|
||||
*/
|
||||
public class BGABadgeRadioButton extends RadioButton implements BGABadgeable {
|
||||
private BGABadgeViewHelper mBadgeViewHeler;
|
||||
|
||||
public BGABadgeRadioButton(Context context) {
|
||||
this(context, null);
|
||||
}
|
||||
|
||||
public BGABadgeRadioButton(Context context, AttributeSet attrs) {
|
||||
this(context, attrs, android.R.attr.radioButtonStyle);
|
||||
}
|
||||
|
||||
public BGABadgeRadioButton(Context context, AttributeSet attrs, int defStyleAttr) {
|
||||
super(context, attrs, defStyleAttr);
|
||||
mBadgeViewHeler = new BGABadgeViewHelper(this, context, attrs, BGABadgeViewHelper.BadgeGravity.RightTop);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onTouchEvent(MotionEvent event) {
|
||||
return mBadgeViewHeler.onTouchEvent(event);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean callSuperOnTouchEvent(MotionEvent event) {
|
||||
return super.onTouchEvent(event);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDraw(Canvas canvas) {
|
||||
super.onDraw(canvas);
|
||||
mBadgeViewHeler.drawBadge(canvas);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void showCirclePointBadge() {
|
||||
mBadgeViewHeler.showCirclePointBadge();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void showTextBadge(String badgeText) {
|
||||
mBadgeViewHeler.showTextBadge(badgeText);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void hiddenBadge() {
|
||||
mBadgeViewHeler.hiddenBadge();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void showDrawableBadge(Bitmap bitmap) {
|
||||
mBadgeViewHeler.showDrawable(bitmap);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setDragDismissDelegage(BGADragDismissDelegate delegate) {
|
||||
mBadgeViewHeler.setDragDismissDelegage(delegate);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isShowBadge() {
|
||||
return mBadgeViewHeler.isShowBadge();
|
||||
}
|
||||
|
||||
@Override
|
||||
public BGABadgeViewHelper getBadgeViewHelper() {
|
||||
return mBadgeViewHeler;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,97 @@
|
||||
/**
|
||||
* Copyright 2015 bingoogolapple
|
||||
* <p/>
|
||||
* 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
|
||||
* <p/>
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* <p/>
|
||||
* 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 cn.bingoogolapple.badgeview;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.Canvas;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.MotionEvent;
|
||||
import android.widget.RelativeLayout;
|
||||
|
||||
/**
|
||||
* 作者:王浩 邮件:bingoogolapple@gmail.com
|
||||
* 创建时间:15/7/7 14:07
|
||||
* 描述:
|
||||
*/
|
||||
public class BGABadgeRelativeLayout extends RelativeLayout implements BGABadgeable {
|
||||
private BGABadgeViewHelper mBadgeViewHeler;
|
||||
|
||||
public BGABadgeRelativeLayout(Context context) {
|
||||
this(context, null);
|
||||
}
|
||||
|
||||
public BGABadgeRelativeLayout(Context context, AttributeSet attrs) {
|
||||
this(context, attrs, 0);
|
||||
}
|
||||
|
||||
public BGABadgeRelativeLayout(Context context, AttributeSet attrs, int defStyleAttr) {
|
||||
super(context, attrs, defStyleAttr);
|
||||
mBadgeViewHeler = new BGABadgeViewHelper(this, context, attrs, BGABadgeViewHelper.BadgeGravity.RightCenter);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onTouchEvent(MotionEvent event) {
|
||||
return mBadgeViewHeler.onTouchEvent(event);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean callSuperOnTouchEvent(MotionEvent event) {
|
||||
return super.onTouchEvent(event);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void dispatchDraw(Canvas canvas) {
|
||||
super.dispatchDraw(canvas);
|
||||
mBadgeViewHeler.drawBadge(canvas);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void showCirclePointBadge() {
|
||||
mBadgeViewHeler.showCirclePointBadge();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void showTextBadge(String badgeText) {
|
||||
mBadgeViewHeler.showTextBadge(badgeText);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void hiddenBadge() {
|
||||
mBadgeViewHeler.hiddenBadge();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void showDrawableBadge(Bitmap bitmap) {
|
||||
mBadgeViewHeler.showDrawable(bitmap);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setDragDismissDelegage(BGADragDismissDelegate delegate) {
|
||||
mBadgeViewHeler.setDragDismissDelegage(delegate);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isShowBadge() {
|
||||
return mBadgeViewHeler.isShowBadge();
|
||||
}
|
||||
|
||||
@Override
|
||||
public BGABadgeViewHelper getBadgeViewHelper() {
|
||||
return mBadgeViewHeler;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,97 @@
|
||||
/**
|
||||
* Copyright 2015 bingoogolapple
|
||||
* <p/>
|
||||
* 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
|
||||
* <p/>
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* <p/>
|
||||
* 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 cn.bingoogolapple.badgeview;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.Canvas;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.MotionEvent;
|
||||
import android.widget.TextView;
|
||||
|
||||
/**
|
||||
* 作者:王浩 邮件:bingoogolapple@gmail.com
|
||||
* 创建时间:15/7/6 下午3:04
|
||||
* 描述:
|
||||
*/
|
||||
public class BGABadgeTextView extends TextView implements BGABadgeable {
|
||||
private BGABadgeViewHelper mBadgeViewHeler;
|
||||
|
||||
public BGABadgeTextView(Context context) {
|
||||
this(context, null);
|
||||
}
|
||||
|
||||
public BGABadgeTextView(Context context, AttributeSet attrs) {
|
||||
this(context, attrs, android.R.attr.textViewStyle);
|
||||
}
|
||||
|
||||
public BGABadgeTextView(Context context, AttributeSet attrs, int defStyleAttr) {
|
||||
super(context, attrs, defStyleAttr);
|
||||
mBadgeViewHeler = new BGABadgeViewHelper(this, context, attrs, BGABadgeViewHelper.BadgeGravity.RightCenter);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onTouchEvent(MotionEvent event) {
|
||||
return mBadgeViewHeler.onTouchEvent(event);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean callSuperOnTouchEvent(MotionEvent event) {
|
||||
return super.onTouchEvent(event);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDraw(Canvas canvas) {
|
||||
super.onDraw(canvas);
|
||||
mBadgeViewHeler.drawBadge(canvas);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void showCirclePointBadge() {
|
||||
mBadgeViewHeler.showCirclePointBadge();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void showTextBadge(String badgeText) {
|
||||
mBadgeViewHeler.showTextBadge(badgeText);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void hiddenBadge() {
|
||||
mBadgeViewHeler.hiddenBadge();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void showDrawableBadge(Bitmap bitmap) {
|
||||
mBadgeViewHeler.showDrawable(bitmap);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setDragDismissDelegage(BGADragDismissDelegate delegate) {
|
||||
mBadgeViewHeler.setDragDismissDelegage(delegate);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isShowBadge() {
|
||||
return mBadgeViewHeler.isShowBadge();
|
||||
}
|
||||
|
||||
@Override
|
||||
public BGABadgeViewHelper getBadgeViewHelper() {
|
||||
return mBadgeViewHeler;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
package cn.bingoogolapple.badgeview;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.Canvas;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.View;
|
||||
|
||||
/**
|
||||
* 作者:王浩 邮件:bingoogolapple@gmail.com
|
||||
* 创建时间:16/3/14 上午2:46
|
||||
* 描述:
|
||||
*/
|
||||
public class BGABadgeView extends View implements BGABadgeable {
|
||||
private BGABadgeViewHelper mBadgeViewHeler;
|
||||
|
||||
public BGABadgeView(Context context) {
|
||||
this(context, null);
|
||||
}
|
||||
|
||||
public BGABadgeView(Context context, AttributeSet attrs) {
|
||||
this(context, attrs, 0);
|
||||
}
|
||||
|
||||
public BGABadgeView(Context context, AttributeSet attrs, int defStyleAttr) {
|
||||
super(context, attrs, defStyleAttr);
|
||||
mBadgeViewHeler = new BGABadgeViewHelper(this, context, attrs, BGABadgeViewHelper.BadgeGravity.RightCenter);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onTouchEvent(MotionEvent event) {
|
||||
return mBadgeViewHeler.onTouchEvent(event);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean callSuperOnTouchEvent(MotionEvent event) {
|
||||
return super.onTouchEvent(event);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDraw(Canvas canvas) {
|
||||
super.onDraw(canvas);
|
||||
mBadgeViewHeler.drawBadge(canvas);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void showCirclePointBadge() {
|
||||
mBadgeViewHeler.showCirclePointBadge();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void showTextBadge(String badgeText) {
|
||||
mBadgeViewHeler.showTextBadge(badgeText);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void hiddenBadge() {
|
||||
mBadgeViewHeler.hiddenBadge();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void showDrawableBadge(Bitmap bitmap) {
|
||||
mBadgeViewHeler.showDrawable(bitmap);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setDragDismissDelegage(BGADragDismissDelegate delegate) {
|
||||
mBadgeViewHeler.setDragDismissDelegage(delegate);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isShowBadge() {
|
||||
return mBadgeViewHeler.isShowBadge();
|
||||
}
|
||||
|
||||
@Override
|
||||
public BGABadgeViewHelper getBadgeViewHelper() {
|
||||
return mBadgeViewHeler;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,513 @@
|
||||
/**
|
||||
* Copyright 2015 bingoogolapple
|
||||
* <p/>
|
||||
* 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
|
||||
* <p/>
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* <p/>
|
||||
* 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 cn.bingoogolapple.badgeview;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.res.TypedArray;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.Paint;
|
||||
import android.graphics.Rect;
|
||||
import android.graphics.RectF;
|
||||
import android.text.TextUtils;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.View;
|
||||
|
||||
/**
|
||||
* 作者:王浩 邮件:bingoogolapple@gmail.com
|
||||
* 创建时间:15/7/6 下午10:13
|
||||
* 描述:
|
||||
*/
|
||||
public class BGABadgeViewHelper {
|
||||
private Bitmap mBitmap;
|
||||
private BGABadgeable mBadgeable;
|
||||
private Paint mBadgePaint;
|
||||
/**
|
||||
* 徽章背景色
|
||||
*/
|
||||
private int mBadgeBgColor;
|
||||
/**
|
||||
* 徽章文本的颜色
|
||||
*/
|
||||
private int mBadgeTextColor;
|
||||
/**
|
||||
* 徽章文本字体大小
|
||||
*/
|
||||
private int mBadgeTextSize;
|
||||
/**
|
||||
* 徽章背景与宿主控件上下边缘间距离
|
||||
*/
|
||||
private int mBadgeVerticalMargin;
|
||||
/**
|
||||
* 徽章背景与宿主控件左右边缘间距离
|
||||
*/
|
||||
private int mBadgeHorizontalMargin;
|
||||
/***
|
||||
* 徽章文本边缘与徽章背景边缘间的距离
|
||||
*/
|
||||
private int mBadgePadding;
|
||||
/**
|
||||
* 徽章文本
|
||||
*/
|
||||
private String mBadgeText;
|
||||
/**
|
||||
* 徽章文本所占区域大小
|
||||
*/
|
||||
private Rect mBadgeNumberRect;
|
||||
/**
|
||||
* 是否显示Badge
|
||||
*/
|
||||
private boolean mIsShowBadge;
|
||||
/**
|
||||
* 徽章在宿主控件中的位置
|
||||
*/
|
||||
private BadgeGravity mBadgeGravity;
|
||||
/**
|
||||
* 整个徽章所占区域
|
||||
*/
|
||||
private RectF mBadgeRectF;
|
||||
/**
|
||||
* 是否可拖动
|
||||
*/
|
||||
private boolean mDragable;
|
||||
/**
|
||||
* 拖拽徽章超出轨迹范围后,再次放回到轨迹范围时,是否恢复轨迹
|
||||
*/
|
||||
private boolean mIsResumeTravel;
|
||||
/***
|
||||
* 徽章描边宽度
|
||||
*/
|
||||
private int mBadgeBorderWidth;
|
||||
/***
|
||||
* 徽章描边颜色
|
||||
*/
|
||||
private int mBadgeBorderColor;
|
||||
/**
|
||||
* 触发开始拖拽徽章事件的扩展触摸距离
|
||||
*/
|
||||
private int mDragExtra;
|
||||
/**
|
||||
* 整个徽章加上其触发开始拖拽区域所占区域
|
||||
*/
|
||||
private RectF mBadgeDragExtraRectF;
|
||||
/**
|
||||
* 拖动时的徽章控件
|
||||
*/
|
||||
private BGADragBadgeView mDropBadgeView;
|
||||
/**
|
||||
* 是否正在拖动
|
||||
*/
|
||||
private boolean mIsDraging;
|
||||
/**
|
||||
* 拖动大于BGABadgeViewHelper.mMoveHiddenThreshold后抬起手指徽章消失的代理
|
||||
*/
|
||||
private BGADragDismissDelegate mDelegage;
|
||||
private boolean mIsShowDrawable = false;
|
||||
|
||||
public BGABadgeViewHelper(BGABadgeable badgeable, Context context, AttributeSet attrs, BadgeGravity defaultBadgeGravity) {
|
||||
mBadgeable = badgeable;
|
||||
initDefaultAttrs(context, defaultBadgeGravity);
|
||||
initCustomAttrs(context, attrs);
|
||||
afterInitDefaultAndCustomAttrs();
|
||||
mDropBadgeView = new BGADragBadgeView(context, this);
|
||||
}
|
||||
|
||||
private void initDefaultAttrs(Context context, BadgeGravity defaultBadgeGravity) {
|
||||
mBadgeNumberRect = new Rect();
|
||||
mBadgeRectF = new RectF();
|
||||
mBadgeBgColor = Color.RED;
|
||||
mBadgeTextColor = Color.WHITE;
|
||||
mBadgeTextSize = BGABadgeViewUtil.sp2px(context, 10);
|
||||
|
||||
mBadgePaint = new Paint();
|
||||
mBadgePaint.setAntiAlias(true);
|
||||
mBadgePaint.setStyle(Paint.Style.FILL);
|
||||
// 设置mBadgeText居中,保证mBadgeText长度为1时,文本也能居中
|
||||
mBadgePaint.setTextAlign(Paint.Align.CENTER);
|
||||
|
||||
mBadgePadding = BGABadgeViewUtil.dp2px(context, 4);
|
||||
mBadgeVerticalMargin = BGABadgeViewUtil.dp2px(context, 4);
|
||||
mBadgeHorizontalMargin = BGABadgeViewUtil.dp2px(context, 4);
|
||||
|
||||
mBadgeGravity = defaultBadgeGravity;
|
||||
mIsShowBadge = false;
|
||||
|
||||
mBadgeText = null;
|
||||
|
||||
mBitmap = null;
|
||||
|
||||
mIsDraging = false;
|
||||
|
||||
mDragable = false;
|
||||
|
||||
mBadgeBorderColor = Color.WHITE;
|
||||
|
||||
mDragExtra = BGABadgeViewUtil.dp2px(context, 4);
|
||||
mBadgeDragExtraRectF = new RectF();
|
||||
}
|
||||
|
||||
private void initCustomAttrs(Context context, AttributeSet attrs) {
|
||||
TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.BGABadgeView);
|
||||
final int N = typedArray.getIndexCount();
|
||||
for (int i = 0; i < N; i++) {
|
||||
initCustomAttr(typedArray.getIndex(i), typedArray);
|
||||
}
|
||||
typedArray.recycle();
|
||||
}
|
||||
|
||||
private void initCustomAttr(int attr, TypedArray typedArray) {
|
||||
if (attr == R.styleable.BGABadgeView_badge_bgColor) {
|
||||
mBadgeBgColor = typedArray.getColor(attr, mBadgeBgColor);
|
||||
} else if (attr == R.styleable.BGABadgeView_badge_textColor) {
|
||||
mBadgeTextColor = typedArray.getColor(attr, mBadgeTextColor);
|
||||
} else if (attr == R.styleable.BGABadgeView_badge_textSize) {
|
||||
mBadgeTextSize = typedArray.getDimensionPixelSize(attr, mBadgeTextSize);
|
||||
} else if (attr == R.styleable.BGABadgeView_badge_verticalMargin) {
|
||||
mBadgeVerticalMargin = typedArray.getDimensionPixelSize(attr, mBadgeVerticalMargin);
|
||||
} else if (attr == R.styleable.BGABadgeView_badge_horizontalMargin) {
|
||||
mBadgeHorizontalMargin = typedArray.getDimensionPixelSize(attr, mBadgeHorizontalMargin);
|
||||
} else if (attr == R.styleable.BGABadgeView_badge_padding) {
|
||||
mBadgePadding = typedArray.getDimensionPixelSize(attr, mBadgePadding);
|
||||
} else if (attr == R.styleable.BGABadgeView_badge_gravity) {
|
||||
int ordinal = typedArray.getInt(attr, mBadgeGravity.ordinal());
|
||||
mBadgeGravity = BadgeGravity.values()[ordinal];
|
||||
} else if (attr == R.styleable.BGABadgeView_badge_dragable) {
|
||||
mDragable = typedArray.getBoolean(attr, mDragable);
|
||||
} else if (attr == R.styleable.BGABadgeView_badge_isResumeTravel) {
|
||||
mIsResumeTravel = typedArray.getBoolean(attr, mIsResumeTravel);
|
||||
} else if (attr == R.styleable.BGABadgeView_badge_borderWidth) {
|
||||
mBadgeBorderWidth = typedArray.getDimensionPixelSize(attr, mBadgeBorderWidth);
|
||||
} else if (attr == R.styleable.BGABadgeView_badge_borderColor) {
|
||||
mBadgeBorderColor = typedArray.getColor(attr, mBadgeBorderColor);
|
||||
} else if (attr == R.styleable.BGABadgeView_badge_dragExtra) {
|
||||
mDragExtra = typedArray.getDimensionPixelSize(attr, mDragExtra);
|
||||
}
|
||||
}
|
||||
|
||||
private void afterInitDefaultAndCustomAttrs() {
|
||||
mBadgePaint.setTextSize(mBadgeTextSize);
|
||||
}
|
||||
|
||||
public void setBadgeBgColorInt(int badgeBgColor) {
|
||||
mBadgeBgColor = badgeBgColor;
|
||||
mBadgeable.postInvalidate();
|
||||
}
|
||||
|
||||
public void setBadgeTextColorInt(int badgeTextColor) {
|
||||
mBadgeTextColor = badgeTextColor;
|
||||
mBadgeable.postInvalidate();
|
||||
}
|
||||
|
||||
public void setBadgeTextSizeSp(int badgetextSize) {
|
||||
if (badgetextSize >= 0) {
|
||||
mBadgeTextSize = BGABadgeViewUtil.sp2px(mBadgeable.getContext(), badgetextSize);
|
||||
mBadgePaint.setTextSize(mBadgeTextSize);
|
||||
mBadgeable.postInvalidate();
|
||||
}
|
||||
}
|
||||
|
||||
public void setBadgeVerticalMarginDp(int badgeVerticalMargin) {
|
||||
if (badgeVerticalMargin >= 0) {
|
||||
mBadgeVerticalMargin = BGABadgeViewUtil.dp2px(mBadgeable.getContext(), badgeVerticalMargin);
|
||||
mBadgeable.postInvalidate();
|
||||
}
|
||||
}
|
||||
|
||||
public void setBadgeHorizontalMarginDp(int badgeHorizontalMargin) {
|
||||
if (badgeHorizontalMargin >= 0) {
|
||||
mBadgeHorizontalMargin = BGABadgeViewUtil.dp2px(mBadgeable.getContext(), badgeHorizontalMargin);
|
||||
mBadgeable.postInvalidate();
|
||||
}
|
||||
}
|
||||
|
||||
public void setBadgePaddingDp(int badgePadding) {
|
||||
if (badgePadding >= 0) {
|
||||
mBadgePadding = BGABadgeViewUtil.dp2px(mBadgeable.getContext(), badgePadding);
|
||||
mBadgeable.postInvalidate();
|
||||
}
|
||||
}
|
||||
|
||||
public void setBadgeGravity(BadgeGravity badgeGravity) {
|
||||
if (badgeGravity != null) {
|
||||
mBadgeGravity = badgeGravity;
|
||||
mBadgeable.postInvalidate();
|
||||
}
|
||||
}
|
||||
|
||||
public void setDragable(boolean dragable) {
|
||||
mDragable = dragable;
|
||||
mBadgeable.postInvalidate();
|
||||
}
|
||||
|
||||
public void setIsResumeTravel(boolean isResumeTravel) {
|
||||
mIsResumeTravel = isResumeTravel;
|
||||
mBadgeable.postInvalidate();
|
||||
}
|
||||
|
||||
public void setBadgeBorderWidthDp(int badgeBorderWidthDp) {
|
||||
if (badgeBorderWidthDp >= 0) {
|
||||
mBadgeBorderWidth = BGABadgeViewUtil.dp2px(mBadgeable.getContext(), badgeBorderWidthDp);
|
||||
mBadgeable.postInvalidate();
|
||||
}
|
||||
}
|
||||
|
||||
public void setBadgeBorderColorInt(int badgeBorderColor) {
|
||||
mBadgeBorderColor = badgeBorderColor;
|
||||
mBadgeable.postInvalidate();
|
||||
}
|
||||
|
||||
public boolean onTouchEvent(MotionEvent event) {
|
||||
switch (event.getAction()) {
|
||||
case MotionEvent.ACTION_DOWN:
|
||||
mBadgeDragExtraRectF.left = mBadgeRectF.left - mDragExtra;
|
||||
mBadgeDragExtraRectF.top = mBadgeRectF.top - mDragExtra;
|
||||
mBadgeDragExtraRectF.right = mBadgeRectF.right + mDragExtra;
|
||||
mBadgeDragExtraRectF.bottom = mBadgeRectF.bottom + mDragExtra;
|
||||
|
||||
if ((mBadgeBorderWidth == 0 || mIsShowDrawable) && mDragable && mIsShowBadge && mBadgeDragExtraRectF.contains(event.getX(), event.getY())) {
|
||||
mIsDraging = true;
|
||||
mBadgeable.getParent().requestDisallowInterceptTouchEvent(true);
|
||||
|
||||
Rect badgeableRect = new Rect();
|
||||
mBadgeable.getGlobalVisibleRect(badgeableRect);
|
||||
mDropBadgeView.setStickCenter(badgeableRect.left + mBadgeRectF.left + mBadgeRectF.width() / 2, badgeableRect.top + mBadgeRectF.top + mBadgeRectF.height() / 2);
|
||||
|
||||
mDropBadgeView.onTouchEvent(event);
|
||||
mBadgeable.postInvalidate();
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
case MotionEvent.ACTION_MOVE:
|
||||
if (mIsDraging) {
|
||||
mDropBadgeView.onTouchEvent(event);
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
case MotionEvent.ACTION_UP:
|
||||
case MotionEvent.ACTION_CANCEL:
|
||||
if (mIsDraging) {
|
||||
mDropBadgeView.onTouchEvent(event);
|
||||
mIsDraging = false;
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return mBadgeable.callSuperOnTouchEvent(event);
|
||||
}
|
||||
|
||||
public void endDragWithDismiss() {
|
||||
hiddenBadge();
|
||||
if (mDelegage != null) {
|
||||
mDelegage.onDismiss(mBadgeable);
|
||||
}
|
||||
}
|
||||
|
||||
public void endDragWithoutDismiss() {
|
||||
mBadgeable.postInvalidate();
|
||||
}
|
||||
|
||||
public void drawBadge(Canvas canvas) {
|
||||
if (mIsShowBadge && !mIsDraging) {
|
||||
if (mIsShowDrawable) {
|
||||
drawDrawableBadge(canvas);
|
||||
} else {
|
||||
drawTextBadge(canvas);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 绘制图像徽章
|
||||
*
|
||||
* @param canvas
|
||||
*/
|
||||
private void drawDrawableBadge(Canvas canvas) {
|
||||
mBadgeRectF.left = mBadgeable.getWidth() - mBadgeHorizontalMargin - mBitmap.getWidth();
|
||||
mBadgeRectF.top = mBadgeVerticalMargin;
|
||||
switch (mBadgeGravity) {
|
||||
case RightTop:
|
||||
mBadgeRectF.top = mBadgeVerticalMargin;
|
||||
break;
|
||||
case RightCenter:
|
||||
mBadgeRectF.top = (mBadgeable.getHeight() - mBitmap.getHeight()) / 2;
|
||||
break;
|
||||
case RightBottom:
|
||||
mBadgeRectF.top = mBadgeable.getHeight() - mBitmap.getHeight() - mBadgeVerticalMargin;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
canvas.drawBitmap(mBitmap, mBadgeRectF.left, mBadgeRectF.top, mBadgePaint);
|
||||
mBadgeRectF.right = mBadgeRectF.left + mBitmap.getWidth();
|
||||
mBadgeRectF.bottom = mBadgeRectF.top + mBitmap.getHeight();
|
||||
}
|
||||
|
||||
/**
|
||||
* 绘制文字徽章
|
||||
*
|
||||
* @param canvas
|
||||
*/
|
||||
private void drawTextBadge(Canvas canvas) {
|
||||
String badgeText = "";
|
||||
if (!TextUtils.isEmpty(mBadgeText)) {
|
||||
badgeText = mBadgeText;
|
||||
}
|
||||
// 获取文本宽所占宽高
|
||||
mBadgePaint.getTextBounds(badgeText, 0, badgeText.length(), mBadgeNumberRect);
|
||||
// 计算徽章背景的宽高
|
||||
int badgeHeight = mBadgeNumberRect.height() + mBadgePadding * 2;
|
||||
int badgeWidth;
|
||||
// 当mBadgeText的长度为1或0时,计算出来的高度会比宽度大,此时设置宽度等于高度
|
||||
if (badgeText.length() == 1 || badgeText.length() == 0) {
|
||||
badgeWidth = badgeHeight;
|
||||
} else {
|
||||
badgeWidth = mBadgeNumberRect.width() + mBadgePadding * 2;
|
||||
}
|
||||
|
||||
// 计算徽章背景上下的值
|
||||
mBadgeRectF.top = mBadgeVerticalMargin;
|
||||
mBadgeRectF.bottom = mBadgeable.getHeight() - mBadgeVerticalMargin;
|
||||
switch (mBadgeGravity) {
|
||||
case RightTop:
|
||||
mBadgeRectF.bottom = mBadgeRectF.top + badgeHeight;
|
||||
break;
|
||||
case RightCenter:
|
||||
mBadgeRectF.top = (mBadgeable.getHeight() - badgeHeight) / 2;
|
||||
mBadgeRectF.bottom = mBadgeRectF.top + badgeHeight;
|
||||
break;
|
||||
case RightBottom:
|
||||
mBadgeRectF.top = mBadgeRectF.bottom - badgeHeight;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
// 计算徽章背景左右的值
|
||||
mBadgeRectF.right = mBadgeable.getWidth() - mBadgeHorizontalMargin;
|
||||
mBadgeRectF.left = mBadgeRectF.right - badgeWidth;
|
||||
|
||||
if (mBadgeBorderWidth > 0) {
|
||||
// 设置徽章边框景色
|
||||
mBadgePaint.setColor(mBadgeBorderColor);
|
||||
// 绘制徽章边框背景
|
||||
canvas.drawRoundRect(mBadgeRectF, badgeHeight / 2, badgeHeight / 2, mBadgePaint);
|
||||
|
||||
// 设置徽章背景色
|
||||
mBadgePaint.setColor(mBadgeBgColor);
|
||||
// 绘制徽章背景
|
||||
canvas.drawRoundRect(new RectF(mBadgeRectF.left + mBadgeBorderWidth, mBadgeRectF.top + mBadgeBorderWidth, mBadgeRectF.right - mBadgeBorderWidth, mBadgeRectF.bottom - mBadgeBorderWidth), (badgeHeight - 2 * mBadgeBorderWidth) / 2, (badgeHeight - 2 * mBadgeBorderWidth) / 2, mBadgePaint);
|
||||
} else {
|
||||
// 设置徽章背景色
|
||||
mBadgePaint.setColor(mBadgeBgColor);
|
||||
// 绘制徽章背景
|
||||
canvas.drawRoundRect(mBadgeRectF, badgeHeight / 2, badgeHeight / 2, mBadgePaint);
|
||||
}
|
||||
|
||||
|
||||
if (!TextUtils.isEmpty(mBadgeText)) {
|
||||
// 设置徽章文本颜色
|
||||
mBadgePaint.setColor(mBadgeTextColor);
|
||||
// initDefaultAttrs方法中设置了mBadgeText居中,此处的x为徽章背景的中心点y
|
||||
float x = mBadgeRectF.left + badgeWidth / 2;
|
||||
// 注意:绘制文本时的y是指文本底部,而不是文本的中间
|
||||
float y = mBadgeRectF.bottom - mBadgePadding;
|
||||
// 绘制徽章文本
|
||||
canvas.drawText(badgeText, x, y, mBadgePaint);
|
||||
}
|
||||
}
|
||||
|
||||
public void showCirclePointBadge() {
|
||||
showTextBadge(null);
|
||||
}
|
||||
|
||||
public void showTextBadge(String badgeText) {
|
||||
mIsShowDrawable = false;
|
||||
mBadgeText = badgeText;
|
||||
mIsShowBadge = true;
|
||||
mBadgeable.postInvalidate();
|
||||
}
|
||||
|
||||
public void hiddenBadge() {
|
||||
mIsShowBadge = false;
|
||||
mBadgeable.postInvalidate();
|
||||
}
|
||||
|
||||
public boolean isShowBadge() {
|
||||
return mIsShowBadge;
|
||||
}
|
||||
|
||||
public void showDrawable(Bitmap bitmap) {
|
||||
mBitmap = bitmap;
|
||||
mIsShowDrawable = true;
|
||||
mIsShowBadge = true;
|
||||
mBadgeable.postInvalidate();
|
||||
}
|
||||
|
||||
public boolean isShowDrawable() {
|
||||
return mIsShowDrawable;
|
||||
}
|
||||
|
||||
public RectF getBadgeRectF() {
|
||||
return mBadgeRectF;
|
||||
}
|
||||
|
||||
public int getBadgePadding() {
|
||||
return mBadgePadding;
|
||||
}
|
||||
|
||||
public String getBadgeText() {
|
||||
return mBadgeText;
|
||||
}
|
||||
|
||||
public int getBadgeBgColor() {
|
||||
return mBadgeBgColor;
|
||||
}
|
||||
|
||||
public int getBadgeTextColor() {
|
||||
return mBadgeTextColor;
|
||||
}
|
||||
|
||||
public int getBadgeTextSize() {
|
||||
return mBadgeTextSize;
|
||||
}
|
||||
|
||||
public Bitmap getBitmap() {
|
||||
return mBitmap;
|
||||
}
|
||||
|
||||
public void setDragDismissDelegage(BGADragDismissDelegate delegage) {
|
||||
mDelegage = delegage;
|
||||
}
|
||||
|
||||
public View getRootView() {
|
||||
return mBadgeable.getRootView();
|
||||
}
|
||||
|
||||
public boolean isResumeTravel() {
|
||||
return mIsResumeTravel;
|
||||
}
|
||||
|
||||
public enum BadgeGravity {
|
||||
RightTop,
|
||||
RightCenter,
|
||||
RightBottom
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,100 @@
|
||||
/**
|
||||
* Copyright 2015 bingoogolapple
|
||||
* <p/>
|
||||
* 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
|
||||
* <p/>
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* <p/>
|
||||
* 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 cn.bingoogolapple.badgeview;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.PointF;
|
||||
import android.graphics.Rect;
|
||||
import android.util.TypedValue;
|
||||
import android.view.View;
|
||||
|
||||
/**
|
||||
* 作者:王浩 邮件:bingoogolapple@gmail.com
|
||||
* 创建时间:15/12/5 上午12:27
|
||||
* 描述:
|
||||
*/
|
||||
public class BGABadgeViewUtil {
|
||||
|
||||
private BGABadgeViewUtil() {
|
||||
}
|
||||
|
||||
public static int dp2px(Context context, float dpValue) {
|
||||
return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dpValue, context.getResources().getDisplayMetrics());
|
||||
}
|
||||
|
||||
public static int sp2px(Context context, float spValue) {
|
||||
return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, spValue, context.getResources().getDisplayMetrics());
|
||||
}
|
||||
|
||||
public static int getStatusBarHeight(View view) {
|
||||
Rect rectangle = new Rect();
|
||||
view.getRootView().getWindowVisibleDisplayFrame(rectangle);
|
||||
return rectangle.top;
|
||||
}
|
||||
|
||||
public static Bitmap createBitmapSafely(BGADragBadgeView dragBadgeView, Rect rect, int retryCount) {
|
||||
try {
|
||||
dragBadgeView.setDrawingCacheEnabled(true);
|
||||
// 只裁剪徽章区域,不然会很卡
|
||||
return Bitmap.createBitmap(dragBadgeView.getDrawingCache(), rect.left < 0 ? 0 : rect.left, rect.top < 0 ? 0 : rect.top, rect.width(), rect.height());
|
||||
} catch (OutOfMemoryError e) {
|
||||
if (retryCount > 0) {
|
||||
System.gc();
|
||||
return createBitmapSafely(dragBadgeView, rect, retryCount - 1);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public static float getDistanceBetween2Points(PointF p0, PointF p1) {
|
||||
float distance = (float) Math.sqrt(Math.pow(p0.y - p1.y, 2) + Math.pow(p0.x - p1.x, 2));
|
||||
return distance;
|
||||
}
|
||||
|
||||
public static PointF getMiddlePoint(PointF p1, PointF p2) {
|
||||
return new PointF((p1.x + p2.x) / 2.0f, (p1.y + p2.y) / 2.0f);
|
||||
}
|
||||
|
||||
public static PointF getPointByPercent(PointF p1, PointF p2, float percent) {
|
||||
return new PointF(evaluate(percent, p1.x, p2.x), evaluate(percent, p1.y, p2.y));
|
||||
}
|
||||
|
||||
// 从FloatEvaluator中拷贝过来,这样就不用每次都new FloatEvaluator了
|
||||
public static Float evaluate(float fraction, Number startValue, Number endValue) {
|
||||
float startFloat = startValue.floatValue();
|
||||
return startFloat + fraction * (endValue.floatValue() - startFloat);
|
||||
}
|
||||
|
||||
public static PointF[] getIntersectionPoints(PointF pMiddle, float radius, Double lineK) {
|
||||
PointF[] points = new PointF[2];
|
||||
|
||||
float radian, xOffset = 0, yOffset = 0;
|
||||
if (lineK != null) {
|
||||
radian = (float) Math.atan(lineK);
|
||||
xOffset = (float) (Math.sin(radian) * radius);
|
||||
yOffset = (float) (Math.cos(radian) * radius);
|
||||
} else {
|
||||
xOffset = radius;
|
||||
yOffset = 0;
|
||||
}
|
||||
points[0] = new PointF(pMiddle.x + xOffset, pMiddle.y - yOffset);
|
||||
points[1] = new PointF(pMiddle.x - xOffset, pMiddle.y + yOffset);
|
||||
|
||||
return points;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,95 @@
|
||||
/**
|
||||
* Copyright 2015 bingoogolapple
|
||||
* <p/>
|
||||
* 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
|
||||
* <p/>
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* <p/>
|
||||
* 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 cn.bingoogolapple.badgeview;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.Rect;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.View;
|
||||
import android.view.ViewParent;
|
||||
|
||||
/**
|
||||
* 作者:王浩 邮件:bingoogolapple@gmail.com
|
||||
* 创建时间:15/7/6 下午10:42
|
||||
* 描述:
|
||||
*/
|
||||
public interface BGABadgeable {
|
||||
/**
|
||||
* 显示圆点徽章
|
||||
*/
|
||||
void showCirclePointBadge();
|
||||
|
||||
/**
|
||||
* 显示文字徽章
|
||||
*
|
||||
* @param badgeText
|
||||
*/
|
||||
void showTextBadge(String badgeText);
|
||||
|
||||
/**
|
||||
* 隐藏徽章
|
||||
*/
|
||||
void hiddenBadge();
|
||||
|
||||
/**
|
||||
* 显示图像徽章
|
||||
*
|
||||
* @param bitmap
|
||||
*/
|
||||
void showDrawableBadge(Bitmap bitmap);
|
||||
|
||||
/**
|
||||
* 调用父类的onTouchEvent方法
|
||||
*
|
||||
* @param event
|
||||
* @return
|
||||
*/
|
||||
boolean callSuperOnTouchEvent(MotionEvent event);
|
||||
|
||||
/**
|
||||
* 拖动大于BGABadgeViewHelper.mMoveHiddenThreshold后抬起手指徽章消失的代理
|
||||
*
|
||||
* @param delegate
|
||||
*/
|
||||
void setDragDismissDelegage(BGADragDismissDelegate delegate);
|
||||
|
||||
/**
|
||||
* 是否显示徽章
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
boolean isShowBadge();
|
||||
|
||||
BGABadgeViewHelper getBadgeViewHelper();
|
||||
|
||||
int getWidth();
|
||||
|
||||
int getHeight();
|
||||
|
||||
void postInvalidate();
|
||||
|
||||
ViewParent getParent();
|
||||
|
||||
int getId();
|
||||
|
||||
boolean getGlobalVisibleRect(Rect r);
|
||||
|
||||
Context getContext();
|
||||
|
||||
View getRootView();
|
||||
}
|
||||
@@ -0,0 +1,478 @@
|
||||
/**
|
||||
* Copyright 2015 bingoogolapple
|
||||
* <p/>
|
||||
* 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
|
||||
* <p/>
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* <p/>
|
||||
* 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 cn.bingoogolapple.badgeview;
|
||||
|
||||
import android.animation.Animator;
|
||||
import android.animation.AnimatorListenerAdapter;
|
||||
import android.animation.ValueAnimator;
|
||||
import android.content.Context;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.Paint;
|
||||
import android.graphics.Path;
|
||||
import android.graphics.PixelFormat;
|
||||
import android.graphics.PointF;
|
||||
import android.graphics.Rect;
|
||||
import android.graphics.RectF;
|
||||
import android.view.Gravity;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.View;
|
||||
import android.view.WindowManager;
|
||||
import android.view.animation.OvershootInterpolator;
|
||||
|
||||
import java.lang.ref.WeakReference;
|
||||
|
||||
|
||||
/**
|
||||
* 作者:王浩 邮件:bingoogolapple@gmail.com
|
||||
* 创建时间:15/7/12 下午3:23
|
||||
* 描述:
|
||||
*/
|
||||
class BGADragBadgeView extends View {
|
||||
private static final String TAG = BGADragBadgeView.class.getSimpleName();
|
||||
private BGABadgeViewHelper mBadgeViewHelper;
|
||||
private Paint mBadgePaint;
|
||||
private WindowManager mWindowManager;
|
||||
private WindowManager.LayoutParams mLayoutParams;
|
||||
private int mStartX;
|
||||
private int mStartY;
|
||||
private BGAExplosionAnimator mExplosionAnimator;
|
||||
private SetExplosionAnimatorNullTask mSetExplosionAnimatorNullTask;
|
||||
|
||||
/**
|
||||
* 针圆切线的切点
|
||||
*/
|
||||
private PointF[] mStickPoints = new PointF[]{
|
||||
new PointF(0, 0),
|
||||
new PointF(0, 0)
|
||||
};
|
||||
/**
|
||||
* 拖拽圆切线的切点
|
||||
*/
|
||||
private PointF[] mDragPoints = new PointF[]{
|
||||
new PointF(0, 0),
|
||||
new PointF(0, 0)
|
||||
};
|
||||
/**
|
||||
* 控制点
|
||||
*/
|
||||
private PointF mControlPoint = new PointF(0, 0);
|
||||
/**
|
||||
* 拖拽圆中心点
|
||||
*/
|
||||
private PointF mDragCenter = new PointF(0, 0);
|
||||
/**
|
||||
* 拖拽圆半径
|
||||
*/
|
||||
private float mDragRadius;
|
||||
|
||||
/**
|
||||
* 针圆中心点
|
||||
*/
|
||||
private PointF mStickCenter;
|
||||
/**
|
||||
* 针圆半径
|
||||
*/
|
||||
private float mStickRadius;
|
||||
/**
|
||||
* 拖拽圆最大半径
|
||||
*/
|
||||
private int mMaxDragRadius;
|
||||
/**
|
||||
* 拖拽圆半径和针圆半径的差值
|
||||
*/
|
||||
private int mDragStickRadiusDifference;
|
||||
/**
|
||||
* 拖动mDismissThreshold距离后抬起手指徽章消失
|
||||
*/
|
||||
private int mDismissThreshold;
|
||||
|
||||
private boolean mDismissAble;
|
||||
private boolean mIsDragDisappear;
|
||||
|
||||
public BGADragBadgeView(Context context, BGABadgeViewHelper badgeViewHelper) {
|
||||
super(context);
|
||||
mWindowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
|
||||
mBadgeViewHelper = badgeViewHelper;
|
||||
initBadgePaint();
|
||||
initLayoutParams();
|
||||
initStick();
|
||||
|
||||
mSetExplosionAnimatorNullTask = new SetExplosionAnimatorNullTask(this);
|
||||
}
|
||||
|
||||
private void initBadgePaint() {
|
||||
mBadgePaint = new Paint();
|
||||
mBadgePaint.setAntiAlias(true);
|
||||
mBadgePaint.setStyle(Paint.Style.FILL);
|
||||
// 设置mBadgeText居中,保证mBadgeText长度为1时,文本也能居中
|
||||
mBadgePaint.setTextAlign(Paint.Align.CENTER);
|
||||
mBadgePaint.setTextSize(mBadgeViewHelper.getBadgeTextSize());
|
||||
}
|
||||
|
||||
private void initLayoutParams() {
|
||||
mLayoutParams = new WindowManager.LayoutParams();
|
||||
mLayoutParams.gravity = Gravity.LEFT + Gravity.TOP;
|
||||
mLayoutParams.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
|
||||
mLayoutParams.format = PixelFormat.TRANSLUCENT;
|
||||
mLayoutParams.type = WindowManager.LayoutParams.TYPE_TOAST;
|
||||
mLayoutParams.width = WindowManager.LayoutParams.MATCH_PARENT;
|
||||
mLayoutParams.height = WindowManager.LayoutParams.MATCH_PARENT;
|
||||
}
|
||||
|
||||
private void initStick() {
|
||||
mMaxDragRadius = BGABadgeViewUtil.dp2px(getContext(), 10);
|
||||
mDragStickRadiusDifference = BGABadgeViewUtil.dp2px(getContext(), 1);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDraw(Canvas canvas) {
|
||||
try {
|
||||
if (mExplosionAnimator == null) {
|
||||
if (mBadgeViewHelper.isShowDrawable()) {
|
||||
if (mBadgeViewHelper.getBadgeBgColor() == Color.RED) {
|
||||
mBadgePaint.setColor(mBadgeViewHelper.getBitmap().getPixel(mBadgeViewHelper.getBitmap().getWidth() / 2, mBadgeViewHelper.getBitmap().getHeight() / 2));
|
||||
} else {
|
||||
mBadgePaint.setColor(mBadgeViewHelper.getBadgeBgColor());
|
||||
}
|
||||
drawStick(canvas);
|
||||
drawDrawableBadge(canvas);
|
||||
} else {
|
||||
mBadgePaint.setColor(mBadgeViewHelper.getBadgeBgColor());
|
||||
drawStick(canvas);
|
||||
drawTextBadge(canvas);
|
||||
}
|
||||
} else {
|
||||
mExplosionAnimator.draw(canvas);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
// 确保自己能被移除
|
||||
removeSelfWithException();
|
||||
}
|
||||
}
|
||||
|
||||
private void drawDrawableBadge(Canvas canvas) {
|
||||
canvas.drawBitmap(mBadgeViewHelper.getBitmap(), mStartX, mStartY, mBadgePaint);
|
||||
}
|
||||
|
||||
private void drawTextBadge(Canvas canvas) {
|
||||
// 设置徽章背景色
|
||||
mBadgePaint.setColor(mBadgeViewHelper.getBadgeBgColor());
|
||||
// 绘制徽章背景
|
||||
canvas.drawRoundRect(new RectF(mStartX, mStartY, mStartX + mBadgeViewHelper.getBadgeRectF().width(), mStartY + mBadgeViewHelper.getBadgeRectF().height()), mBadgeViewHelper.getBadgeRectF().height() / 2, mBadgeViewHelper.getBadgeRectF().height() / 2, mBadgePaint);
|
||||
|
||||
// 设置徽章文本颜色
|
||||
mBadgePaint.setColor(mBadgeViewHelper.getBadgeTextColor());
|
||||
float x = mStartX + mBadgeViewHelper.getBadgeRectF().width() / 2;
|
||||
// 注意:绘制文本时的y是指文本底部,而不是文本的中间
|
||||
float y = mStartY + mBadgeViewHelper.getBadgeRectF().height() - mBadgeViewHelper.getBadgePadding();
|
||||
// 绘制徽章文本
|
||||
String badgeText = mBadgeViewHelper.getBadgeText() == null ? "" : mBadgeViewHelper.getBadgeText();
|
||||
canvas.drawText(badgeText, x, y, mBadgePaint);
|
||||
}
|
||||
|
||||
private void drawStick(Canvas canvas) {
|
||||
float currentStickRadius = getCurrentStickRadius();
|
||||
|
||||
// 2. 获取直线与圆的交点
|
||||
float yOffset = mStickCenter.y - mDragCenter.y;
|
||||
float xOffset = mStickCenter.x - mDragCenter.x;
|
||||
Double lineK = null;
|
||||
if (xOffset != 0) {
|
||||
lineK = (double) (yOffset / xOffset);
|
||||
}
|
||||
// 通过几何图形工具获取交点坐标
|
||||
mDragPoints = BGABadgeViewUtil.getIntersectionPoints(mDragCenter, mDragRadius, lineK);
|
||||
mStickPoints = BGABadgeViewUtil.getIntersectionPoints(mStickCenter, currentStickRadius, lineK);
|
||||
|
||||
// 3. 获取控制点坐标
|
||||
mControlPoint = BGABadgeViewUtil.getMiddlePoint(mDragCenter, mStickCenter);
|
||||
|
||||
// 保存画布状态
|
||||
canvas.save();
|
||||
canvas.translate(0, -BGABadgeViewUtil.getStatusBarHeight(mBadgeViewHelper.getRootView()));
|
||||
|
||||
if (!mIsDragDisappear) {
|
||||
if (!mDismissAble) {
|
||||
|
||||
// 3. 画连接部分
|
||||
Path path = new Path();
|
||||
// 跳到点1
|
||||
path.moveTo(mStickPoints[0].x, mStickPoints[0].y);
|
||||
// 画曲线1 -> 2
|
||||
path.quadTo(mControlPoint.x, mControlPoint.y, mDragPoints[0].x, mDragPoints[0].y);
|
||||
// 画直线2 -> 3
|
||||
path.lineTo(mDragPoints[1].x, mDragPoints[1].y);
|
||||
// 画曲线3 -> 4
|
||||
path.quadTo(mControlPoint.x, mControlPoint.y, mStickPoints[1].x, mStickPoints[1].y);
|
||||
path.close();
|
||||
canvas.drawPath(path, mBadgePaint);
|
||||
|
||||
// 2. 画固定圆
|
||||
canvas.drawCircle(mStickCenter.x, mStickCenter.y, currentStickRadius, mBadgePaint);
|
||||
}
|
||||
|
||||
// 1. 画拖拽圆
|
||||
canvas.drawCircle(mDragCenter.x, mDragCenter.y, mDragRadius, mBadgePaint);
|
||||
}
|
||||
|
||||
// 恢复上次的保存状态
|
||||
canvas.restore();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取针圆实时半径
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
private float getCurrentStickRadius() {
|
||||
/**
|
||||
* distance 0 -> mDismissThreshold
|
||||
* percent 0.0f -> 1.0f
|
||||
* currentStickRadius mStickRadius * 100% -> mStickRadius * 20%
|
||||
*/
|
||||
float distance = BGABadgeViewUtil.getDistanceBetween2Points(mDragCenter, mStickCenter);
|
||||
distance = Math.min(distance, mDismissThreshold);
|
||||
float percent = distance / mDismissThreshold;
|
||||
return BGABadgeViewUtil.evaluate(percent, mStickRadius, mStickRadius * 0.2f);
|
||||
}
|
||||
|
||||
public void setStickCenter(float x, float y) {
|
||||
mStickCenter = new PointF(x, y);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onTouchEvent(MotionEvent event) {
|
||||
try {
|
||||
switch (event.getAction()) {
|
||||
case MotionEvent.ACTION_DOWN:
|
||||
handleActionDown(event);
|
||||
break;
|
||||
case MotionEvent.ACTION_MOVE:
|
||||
handleActionMove(event);
|
||||
break;
|
||||
case MotionEvent.ACTION_UP:
|
||||
case MotionEvent.ACTION_CANCEL:
|
||||
handleActionUp(event);
|
||||
break;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
// 确保自己能被移除
|
||||
removeSelfWithException();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private void handleActionDown(MotionEvent event) {
|
||||
if (mExplosionAnimator == null && getParent() == null) {
|
||||
mDragRadius = Math.min(mBadgeViewHelper.getBadgeRectF().width() / 2, mMaxDragRadius);
|
||||
mStickRadius = mDragRadius - mDragStickRadiusDifference;
|
||||
mDismissThreshold = (int) (mStickRadius * 10);
|
||||
|
||||
mDismissAble = false;
|
||||
mIsDragDisappear = false;
|
||||
|
||||
mWindowManager.addView(this, mLayoutParams);
|
||||
|
||||
updateDragPosition(event.getRawX(), event.getRawY());
|
||||
}
|
||||
}
|
||||
|
||||
private void handleActionMove(MotionEvent event) {
|
||||
if (mExplosionAnimator == null && getParent() != null) {
|
||||
updateDragPosition(event.getRawX(), event.getRawY());
|
||||
|
||||
// 处理断开事件
|
||||
if (BGABadgeViewUtil.getDistanceBetween2Points(mDragCenter, mStickCenter) > mDismissThreshold) {
|
||||
mDismissAble = true;
|
||||
postInvalidate();
|
||||
} else if (mBadgeViewHelper.isResumeTravel()) {
|
||||
mDismissAble = false;
|
||||
postInvalidate();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void handleActionUp(MotionEvent event) {
|
||||
handleActionMove(event);
|
||||
|
||||
if (mDismissAble) {
|
||||
// 拖拽点超出过范围
|
||||
if (BGABadgeViewUtil.getDistanceBetween2Points(mDragCenter, mStickCenter) > mDismissThreshold) {
|
||||
// 现在也超出范围,消失
|
||||
try {
|
||||
mIsDragDisappear = true;
|
||||
startDismissAnim(getNewStartX(event.getRawX()), getNewStartY(event.getRawY()));
|
||||
} catch (Exception e) {
|
||||
removeSelf();
|
||||
mBadgeViewHelper.endDragWithDismiss();
|
||||
}
|
||||
} else {
|
||||
// 现在没有超出范围,放回去
|
||||
removeSelf();
|
||||
mBadgeViewHelper.endDragWithoutDismiss();
|
||||
}
|
||||
} else {
|
||||
// 拖拽点没超出过范围,弹回去
|
||||
try {
|
||||
startSpringAnim();
|
||||
} catch (Exception e) {
|
||||
removeSelf();
|
||||
mBadgeViewHelper.endDragWithoutDismiss();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void startSpringAnim() {
|
||||
final PointF startReleaseDragCenter = new PointF(mDragCenter.x, mDragCenter.y);
|
||||
ValueAnimator springAnim = ValueAnimator.ofFloat(1.0f);
|
||||
springAnim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
|
||||
|
||||
@Override
|
||||
public void onAnimationUpdate(ValueAnimator mAnim) {
|
||||
// 0.0 -> 1.0f
|
||||
float percent = mAnim.getAnimatedFraction();
|
||||
PointF p = BGABadgeViewUtil.getPointByPercent(startReleaseDragCenter, mStickCenter, percent);
|
||||
updateDragPosition(p.x, p.y);
|
||||
}
|
||||
});
|
||||
springAnim.addListener(new AnimatorListenerAdapter() {
|
||||
@Override
|
||||
public void onAnimationEnd(Animator animation) {
|
||||
removeSelf();
|
||||
mBadgeViewHelper.endDragWithoutDismiss();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAnimationCancel(Animator animation) {
|
||||
removeSelf();
|
||||
mBadgeViewHelper.endDragWithoutDismiss();
|
||||
}
|
||||
});
|
||||
|
||||
springAnim.setInterpolator(new OvershootInterpolator(4));
|
||||
springAnim.setRepeatCount(1);
|
||||
springAnim.setRepeatMode(ValueAnimator.INFINITE);
|
||||
springAnim.setDuration(BGAExplosionAnimator.ANIM_DURATION / 2);
|
||||
springAnim.start();
|
||||
}
|
||||
|
||||
private void startDismissAnim(int newX, int newY) {
|
||||
int badgeWidth = (int) mBadgeViewHelper.getBadgeRectF().width();
|
||||
int badgeHeight = (int) mBadgeViewHelper.getBadgeRectF().height();
|
||||
Rect rect = new Rect(newX - badgeWidth / 2, newY - badgeHeight / 2, newX + badgeWidth / 2, newY + badgeHeight / 2);
|
||||
|
||||
Bitmap badgeBitmap = BGABadgeViewUtil.createBitmapSafely(this, rect, 1);
|
||||
if (badgeBitmap == null) {
|
||||
removeSelf();
|
||||
mBadgeViewHelper.endDragWithDismiss();
|
||||
return;
|
||||
}
|
||||
|
||||
if (mExplosionAnimator != null) {
|
||||
removeSelf();
|
||||
mBadgeViewHelper.endDragWithDismiss();
|
||||
return;
|
||||
}
|
||||
|
||||
mExplosionAnimator = new BGAExplosionAnimator(this, rect, badgeBitmap);
|
||||
mExplosionAnimator.addListener(new AnimatorListenerAdapter() {
|
||||
@Override
|
||||
public void onAnimationEnd(Animator animation) {
|
||||
removeSelf();
|
||||
mBadgeViewHelper.endDragWithDismiss();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAnimationCancel(Animator animation) {
|
||||
removeSelf();
|
||||
mBadgeViewHelper.endDragWithDismiss();
|
||||
}
|
||||
});
|
||||
mExplosionAnimator.start();
|
||||
}
|
||||
|
||||
private void removeSelf() {
|
||||
if (getParent() != null) {
|
||||
mWindowManager.removeView(this);
|
||||
}
|
||||
mDismissAble = false;
|
||||
mIsDragDisappear = false;
|
||||
|
||||
// 处理有时候爆炸效果结束后出现一瞬间的拖拽效果
|
||||
postDelayed(mSetExplosionAnimatorNullTask, 60);
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改拖拽位置
|
||||
*
|
||||
* @param rawX
|
||||
* @param rawY
|
||||
*/
|
||||
private void updateDragPosition(float rawX, float rawY) {
|
||||
mStartX = getNewStartX(rawX);
|
||||
mStartY = getNewStartY(rawY);
|
||||
|
||||
mDragCenter.set(rawX, rawY);
|
||||
postInvalidate();
|
||||
}
|
||||
|
||||
private int getNewStartX(float rawX) {
|
||||
int badgeWidth = (int) mBadgeViewHelper.getBadgeRectF().width();
|
||||
int newX = (int) rawX - badgeWidth / 2;
|
||||
if (newX < 0) {
|
||||
newX = 0;
|
||||
}
|
||||
if (newX > mWindowManager.getDefaultDisplay().getWidth() - badgeWidth) {
|
||||
newX = mWindowManager.getDefaultDisplay().getWidth() - badgeWidth;
|
||||
}
|
||||
return newX;
|
||||
}
|
||||
|
||||
private int getNewStartY(float rawY) {
|
||||
int badgeHeight = (int) mBadgeViewHelper.getBadgeRectF().height();
|
||||
int maxNewY = getHeight() - badgeHeight;
|
||||
int newStartY = (int) rawY - badgeHeight / 2 - BGABadgeViewUtil.getStatusBarHeight(mBadgeViewHelper.getRootView());
|
||||
return Math.min(Math.max(0, newStartY), maxNewY);
|
||||
}
|
||||
|
||||
private void removeSelfWithException() {
|
||||
removeSelf();
|
||||
if (BGABadgeViewUtil.getDistanceBetween2Points(mDragCenter, mStickCenter) > mDismissThreshold) {
|
||||
mBadgeViewHelper.endDragWithDismiss();
|
||||
} else {
|
||||
mBadgeViewHelper.endDragWithoutDismiss();
|
||||
}
|
||||
}
|
||||
|
||||
private static class SetExplosionAnimatorNullTask implements Runnable {
|
||||
private final WeakReference<BGADragBadgeView> mDragBadgeView;
|
||||
|
||||
public SetExplosionAnimatorNullTask(BGADragBadgeView dragBadgeView) {
|
||||
mDragBadgeView = new WeakReference<>(dragBadgeView);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
BGADragBadgeView dragBadgeView = mDragBadgeView.get();
|
||||
if (dragBadgeView != null) {
|
||||
dragBadgeView.mExplosionAnimator = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
/**
|
||||
* Copyright 2015 bingoogolapple
|
||||
* <p/>
|
||||
* 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
|
||||
* <p/>
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* <p/>
|
||||
* 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 cn.bingoogolapple.badgeview;
|
||||
|
||||
/**
|
||||
* 作者:王浩 邮件:bingoogolapple@gmail.com
|
||||
* 创建时间:15/7/12 下午6:33
|
||||
* 描述:拖动大于BGABadgeViewHelper.mMoveHiddenThreshold后抬起手指徽章消失的代理
|
||||
*/
|
||||
public interface BGADragDismissDelegate {
|
||||
|
||||
/**
|
||||
* 拖动大于BGABadgeViewHelper.mMoveHiddenThreshold后抬起手指徽章消失的回调方法
|
||||
*
|
||||
* @param badgeable
|
||||
*/
|
||||
void onDismiss(BGABadgeable badgeable);
|
||||
}
|
||||
@@ -0,0 +1,170 @@
|
||||
/**
|
||||
* Copyright 2015 bingoogolapple
|
||||
* <p/>
|
||||
* 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
|
||||
* <p/>
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* <p/>
|
||||
* 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 cn.bingoogolapple.badgeview;
|
||||
|
||||
import android.animation.ValueAnimator;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.Paint;
|
||||
import android.graphics.Rect;
|
||||
import android.view.animation.AccelerateInterpolator;
|
||||
import android.view.animation.Interpolator;
|
||||
|
||||
import java.util.Random;
|
||||
|
||||
/**
|
||||
* 作者:王浩 邮件:bingoogolapple@gmail.com
|
||||
* 创建时间:15/12/5 上午12:21
|
||||
* 描述:参考https://github.com/tyrantgit/ExplosionField改成了只有一个View的情况,只刷新徽章附近的区域
|
||||
*/
|
||||
public class BGAExplosionAnimator extends ValueAnimator {
|
||||
public static final int ANIM_DURATION = 300;
|
||||
private static final Interpolator DEFAULT_INTERPOLATOR = new AccelerateInterpolator(0.6f);
|
||||
private static final float END_VALUE = 1.4f;
|
||||
private static final int REFRESH_RATIO = 3;
|
||||
private static float X;
|
||||
private static float Y;
|
||||
private static float V;
|
||||
private static float W;
|
||||
|
||||
private Particle[] mParticles;
|
||||
private Paint mPaint;
|
||||
private BGADragBadgeView mDragBadgeView;
|
||||
private Rect mRect;
|
||||
private Rect mInvalidateRect;
|
||||
|
||||
public BGAExplosionAnimator(BGADragBadgeView dragBadgeView, Rect rect, Bitmap bitmap) {
|
||||
setFloatValues(0.0f, END_VALUE);
|
||||
setDuration(ANIM_DURATION);
|
||||
setInterpolator(DEFAULT_INTERPOLATOR);
|
||||
|
||||
X = BGABadgeViewUtil.dp2px(dragBadgeView.getContext(), 5);
|
||||
Y = BGABadgeViewUtil.dp2px(dragBadgeView.getContext(), 20);
|
||||
V = BGABadgeViewUtil.dp2px(dragBadgeView.getContext(), 2);
|
||||
W = BGABadgeViewUtil.dp2px(dragBadgeView.getContext(), 1);
|
||||
|
||||
mPaint = new Paint();
|
||||
mDragBadgeView = dragBadgeView;
|
||||
mRect = rect;
|
||||
mInvalidateRect = new Rect(mRect.left - mRect.width() * REFRESH_RATIO, mRect.top - mRect.height() * REFRESH_RATIO, mRect.right + mRect.width() * REFRESH_RATIO, mRect.bottom + mRect.height() * REFRESH_RATIO);
|
||||
|
||||
int partLen = 15;
|
||||
mParticles = new Particle[partLen * partLen];
|
||||
Random random = new Random(System.currentTimeMillis());
|
||||
int w = bitmap.getWidth() / (partLen + 2);
|
||||
int h = bitmap.getHeight() / (partLen + 2);
|
||||
for (int i = 0; i < partLen; i++) {
|
||||
for (int j = 0; j < partLen; j++) {
|
||||
mParticles[(i * partLen) + j] = generateParticle(bitmap.getPixel((j + 1) * w, (i + 1) * h), random);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private Particle generateParticle(int color, Random random) {
|
||||
Particle particle = new Particle();
|
||||
particle.color = color;
|
||||
particle.radius = V;
|
||||
if (random.nextFloat() < 0.2f) {
|
||||
particle.baseRadius = V + ((X - V) * random.nextFloat());
|
||||
} else {
|
||||
particle.baseRadius = W + ((V - W) * random.nextFloat());
|
||||
}
|
||||
float nextFloat = random.nextFloat();
|
||||
particle.top = mRect.height() * ((0.18f * random.nextFloat()) + 0.2f);
|
||||
particle.top = nextFloat < 0.2f ? particle.top : particle.top + ((particle.top * 0.2f) * random.nextFloat());
|
||||
particle.bottom = (mRect.height() * (random.nextFloat() - 0.5f)) * 1.8f;
|
||||
float f = nextFloat < 0.2f ? particle.bottom : nextFloat < 0.8f ? particle.bottom * 0.6f : particle.bottom * 0.3f;
|
||||
particle.bottom = f;
|
||||
particle.mag = 4.0f * particle.top / particle.bottom;
|
||||
particle.neg = (-particle.mag) / particle.bottom;
|
||||
f = mRect.centerX() + (Y * (random.nextFloat() - 0.5f));
|
||||
particle.baseCx = f + mRect.width() / 2;
|
||||
particle.cx = particle.baseCx;
|
||||
f = mRect.centerY() + (Y * (random.nextFloat() - 0.5f));
|
||||
particle.baseCy = f;
|
||||
particle.cy = f;
|
||||
particle.life = END_VALUE / 10 * random.nextFloat();
|
||||
particle.overflow = 0.4f * random.nextFloat();
|
||||
particle.alpha = 1f;
|
||||
return particle;
|
||||
}
|
||||
|
||||
public void draw(Canvas canvas) {
|
||||
if (!isStarted()) {
|
||||
return;
|
||||
}
|
||||
for (Particle particle : mParticles) {
|
||||
particle.advance((float) getAnimatedValue());
|
||||
if (particle.alpha > 0f) {
|
||||
mPaint.setColor(particle.color);
|
||||
mPaint.setAlpha((int) (Color.alpha(particle.color) * particle.alpha));
|
||||
canvas.drawCircle(particle.cx, particle.cy, particle.radius, mPaint);
|
||||
}
|
||||
}
|
||||
postInvalidate();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void start() {
|
||||
super.start();
|
||||
postInvalidate();
|
||||
}
|
||||
|
||||
/**
|
||||
* 只刷新徽章附近的区域
|
||||
*/
|
||||
private void postInvalidate() {
|
||||
mDragBadgeView.postInvalidate(mInvalidateRect.left, mInvalidateRect.top, mInvalidateRect.right, mInvalidateRect.bottom);
|
||||
}
|
||||
|
||||
private class Particle {
|
||||
float alpha;
|
||||
int color;
|
||||
float cx;
|
||||
float cy;
|
||||
float radius;
|
||||
float baseCx;
|
||||
float baseCy;
|
||||
float baseRadius;
|
||||
float top;
|
||||
float bottom;
|
||||
float mag;
|
||||
float neg;
|
||||
float life;
|
||||
float overflow;
|
||||
|
||||
public void advance(float factor) {
|
||||
float f = 0f;
|
||||
float normalization = factor / END_VALUE;
|
||||
if (normalization < life || normalization > 1f - overflow) {
|
||||
alpha = 0f;
|
||||
return;
|
||||
}
|
||||
normalization = (normalization - life) / (1f - life - overflow);
|
||||
float f2 = normalization * END_VALUE;
|
||||
if (normalization >= 0.7f) {
|
||||
f = (normalization - 0.7f) / 0.3f;
|
||||
}
|
||||
alpha = 1f - f;
|
||||
f = bottom * f2;
|
||||
cx = baseCx + f;
|
||||
cy = (float) (baseCy - this.neg * Math.pow(f, 2.0)) - f * mag;
|
||||
radius = V + (baseRadius - V) * f2;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<declare-styleable name="BGABadgeView">
|
||||
<!-- 徽章背景色 -->
|
||||
<attr name="badge_bgColor" format="reference|color" />
|
||||
<!-- 徽章文本的颜色 -->
|
||||
<attr name="badge_textColor" format="reference|color" />
|
||||
<!-- 徽章文本字体大小 -->
|
||||
<attr name="badge_textSize" format="reference|dimension" />
|
||||
<!-- 徽章背景与宿主控件上下边缘间距离 -->
|
||||
<attr name="badge_verticalMargin" format="reference|dimension" />
|
||||
<!-- 徽章背景与宿主控件左右边缘间距离 -->
|
||||
<attr name="badge_horizontalMargin" format="reference|dimension" />
|
||||
<!-- 徽章文本边缘与徽章背景边缘间的距离 -->
|
||||
<attr name="badge_padding" format="reference|dimension" />
|
||||
<!-- 徽章在宿主控件中的位置 -->
|
||||
<attr name="badge_gravity" format="enum">
|
||||
<enum name="rightTop" value="0" />
|
||||
<enum name="rightCenter" value="1" />
|
||||
<enum name="rightBottom" value="2" />
|
||||
</attr>
|
||||
<!-- 是否可以拖拽删除徽章 -->
|
||||
<attr name="badge_dragable" format="boolean" />
|
||||
<!-- 拖拽徽章超出轨迹范围后,再次放回到轨迹范围时,是否恢复轨迹 -->
|
||||
<attr name="badge_isResumeTravel" format="boolean" />
|
||||
<!-- 徽章描边宽度 -->
|
||||
<attr name="badge_borderWidth" format="reference|dimension" />
|
||||
<!-- 徽章描边颜色 -->
|
||||
<attr name="badge_borderColor" format="reference|color" />
|
||||
<!-- 触发开始拖拽徽章事件的扩展触摸距离-->
|
||||
<attr name="badge_dragExtra" format="reference|dimension" />
|
||||
</declare-styleable>
|
||||
</resources>
|
||||
Reference in New Issue
Block a user