这是在GitHub上找到的一个mode,经过我的一下午的调试终于可以用了。
MainActivity:
package com.example.mylastitemmessage;
import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.widget.Toast;
public class MainActivity extends Activity implements DraggableFlagView.OnDraggableFlagViewListener, View.OnClickListener {
private DraggableFlagView draggableFlagView;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
findViewById(R.id.main_btn).setOnClickListener(this);
draggableFlagView = (DraggableFlagView) findViewById(R.id.main_dfv);
draggableFlagView.setOnDraggableFlagViewListener(this);
draggableFlagView.setText("7");
}
@Override
public void onFlagDismiss(DraggableFlagView view) {
Toast.makeText(this, "onFlagDismiss", Toast.LENGTH_SHORT).show();
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.main_btn:
draggableFlagView.setText("7");
break;
}
}
}
DraggableFlagView:
package com.example.mylastitemmessage;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.ValueAnimator;
import android.app.Activity;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.Point;
import android.text.TextPaint;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.animation.BounceInterpolator;
import android.widget.RelativeLayout;
import java.util.logging.Logger;
/**
* Author: wangjie
* Email: tiantian.china.2@gmail.com
* Github: https://github.com/wangjiegulu/DraggableFlagView
* Date: 12/23/14.
*/
public class DraggableFlagView extends View {
private static final String TAG = DraggableFlagView.class.getSimpleName();
public static interface OnDraggableFlagViewListener {
/**
* 拖拽销毁圆点后的回调
*
* @param view
*/
void onFlagDismiss(DraggableFlagView view);
}
private OnDraggableFlagViewListener onDraggableFlagViewListener;
public void setOnDraggableFlagViewListener(OnDraggableFlagViewListener onDraggableFlagViewListener) {
this.onDraggableFlagViewListener = onDraggableFlagViewListener;
}
public DraggableFlagView(Context context) {
super(context);
init(context);
}
private int patientColor = Color.RED;
public DraggableFlagView(Context context, AttributeSet attrs) {
super(context, attrs);
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.DraggableFlagView);
int indexCount = a.getIndexCount();
for (int i = 0; i < indexCount; i++) {
int attrIndex = a.getIndex(i);
patientColor = a.getColor(attrIndex, Color.RED);
}
a.recycle();
init(context);
}
public DraggableFlagView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init(context);
}
private Context context;
private int originRadius; // 初始的圆的半径
private int originWidth;
private int originHeight;
private int maxMoveLength; // 最大的移动拉长距离
private boolean isArrivedMaxMoved; // 达到了最大的拉长距离(松手可以触发事件)
private int curRadius; // 当前点的半径
private int touchedPointRadius; // touch的圆的半径
private Point startPoint = new Point();
private Point endPoint = new Point();
private Paint paint; // 绘制圆形图形
private TextPaint textPaint; // 绘制圆形图形
private Paint.FontMetrics textFontMetrics;
private int[] location;
private boolean isTouched; // 是否是触摸状态
private Triangle triangle = new Triangle();
private String text = ""; // 正常状态下显示的文字
private void init(Context context) {
this.context = context;
setBackgroundColor(Color.TRANSPARENT);
// 设置绘制flag的paint
paint = new Paint();
paint.setColor(patientColor);
paint.setAntiAlias(true);
// 设置绘制文字的paint
textPaint = new TextPaint();
textPaint.setAntiAlias(true);
textPaint.setColor(Color.WHITE);
textPaint.setTextSize(ABTextUtil.sp2px(context, 12));
textPaint.setTextAlign(Paint.Align.CENTER);
textFontMetrics = textPaint.getFontMetrics();
}
RelativeLayout.LayoutParams originLp; // 实际的layoutparams
RelativeLayout.LayoutParams newLp; // 触摸时候的LayoutParams
private boolean isFirst = true;
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
// Logger.d(TAG, String.format("onSizeChanged, w: %s, h: %s, oldw: %s, oldh: %s", w, h, oldw, oldh));
if (isFirst && w > 0 && h > 0) {
isFirst = false;
originWidth = w;
originHeight = h;
originRadius = Math.min(originWidth, originHeight) / 2;
curRadius = originRadius;
touchedPointRadius = originRadius;
maxMoveLength = ABAppUtil.getDeviceHeight(context) / 6;/
refreshStartPoint();
ViewGroup.LayoutParams lp = this.getLayoutParams();
if (RelativeLayout.LayoutParams.class.isAssignableFrom(lp.getClass())) {
originLp = (RelativeLayout.LayoutParams) lp;
}
newLp = new RelativeLayout.LayoutParams(lp.width, lp.height);
}
}
@Override
public void setLayoutParams(ViewGroup.LayoutParams params) {
super.setLayoutParams(params);
refreshStartPoint();
}
/**
* 修改layoutParams后,需要重新设置startPoint
*/
private void refreshStartPoint() {
location = new int[2];
this.getLocationInWindow(location);
// Logger.d(TAG, "location on screen: " + Arrays.toString(location));
// startPoint.set(location[0], location[1] + h);
try {
location[1] = location[1] - ABAppUtil.getTopBarHeight((Activity) context);///
} catch (Exception ex) {
}
startPoint.set(location[0], location[1] + getMeasuredHeight());
// Logger.d(TAG, "startPoint: " + startPoint);
}
Path path = new Path();
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.drawColor(Color.TRANSPARENT);
int startCircleX = 0, startCircleY = 0;
if (isTouched) { // 触摸状态
startCircleX = startPoint.x + curRadius;
startCircleY = startPoint.y - curRadius;
// 绘制原来的圆形(触摸移动的时候半径会不断变化)
canvas.drawCircle(startCircleX, startCircleY, curRadius, paint);
// 绘制手指跟踪的圆形
int endCircleX = endPoint.x;
int endCircleY = endPoint.y;
canvas.drawCircle(endCircleX, endCircleY, originRadius, paint);
if (!isArrivedMaxMoved) { // 没有达到拉伸最大值
path.reset();
double sin = triangle.deltaY / triangle.hypotenuse;
double cos = triangle.deltaX / triangle.hypotenuse;
// A点
path.moveTo(
(float) (startCircleX - curRadius * sin),
(float) (startCircleY - curRadius * cos)
);
// B点
path.lineTo(
(float) (startCircleX + curRadius * sin),
(float) (startCircleY + curRadius * cos)
);
// C点
path.quadTo(
(startCircleX + endCircleX) / 2, (startCircleY + endCircleY) / 2,
(float) (endCircleX + originRadius * sin), (float) (endCircleY + originRadius * cos)
);
// D点
path.lineTo(
(float) (endCircleX - originRadius * sin),
(float) (endCircleY - originRadius * cos)
);
// A点
path.quadTo(
(startCircleX + endCircleX) / 2, (startCircleY + endCircleY) / 2,
(float) (startCircleX - curRadius * sin), (float) (startCircleY - curRadius * cos)
);
canvas.drawPath(path, paint);
}
// 绘制文字
float textH = - textFontMetrics.ascent - textFontMetrics.descent;
canvas.drawText(text, endCircleX, endCircleY + textH / 2, textPaint);
} else { // 非触摸状态
if (curRadius > 0) {
startCircleX = curRadius;
startCircleY = originHeight - curRadius;
canvas.drawCircle(startCircleX, startCircleY, curRadius, paint);
if (curRadius == originRadius) { // 只有在恢复正常的情况下才显示文字
// 绘制文字
float textH = - textFontMetrics.ascent - textFontMetrics.descent;
canvas.drawText(text, startCircleX, startCircleY + textH / 2, textPaint);
}
}
}
// Logger.d(TAG, "circleX: " + startCircleX + ", circleY: " + startCircleY + ", curRadius: " + curRadius);
}
float downX = Float.MAX_VALUE;
float downY = Float.MAX_VALUE;
@Override
public boolean onTouchEvent(MotionEvent event) {
super.onTouchEvent(event);
// Logger.d(TAG, "onTouchEvent: " + event);
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
isTouched = true;
this.setLayoutParams(newLp);
endPoint.x = (int) downX;
endPoint.y = (int) downY;
changeViewHeight(this, ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
postInvalidate();
downX = event.getX() + location[0];
downY = event.getY() + location[1];
// Logger.d(TAG, String.format("downX: %f, downY: %f", downX, downY));
break;
case MotionEvent.ACTION_MOVE:
// 计算直角边和斜边(用于计算绘制两圆之间的填充去)
triangle.deltaX = event.getX() - downX;
triangle.deltaY = -1 * (event.getY() - downY); // y轴方向相反,所有需要取反
double distance = Math.sqrt(triangle.deltaX * triangle.deltaX + triangle.deltaY * triangle.deltaY);
triangle.hypotenuse = distance;
// Logger.d(TAG, "triangle: " + triangle);
refreshCurRadiusByMoveDistance((int) distance);
endPoint.x = (int) event.getX();
endPoint.y = (int) event.getY();
postInvalidate();
break;
case MotionEvent.ACTION_UP:
isTouched = false;
this.setLayoutParams(originLp);
if (isArrivedMaxMoved) { // 触发事件
changeViewHeight(this, originWidth, originHeight);
postInvalidate();
if (null != onDraggableFlagViewListener) {
onDraggableFlagViewListener.onFlagDismiss(this);
}
// Logger.d(TAG, "触发事件...");
resetAfterDismiss();
} else { // 还原
changeViewHeight(this, originWidth, originHeight);
startRollBackAnimation(500/*ms*/);
}
downX = Float.MAX_VALUE;
downY = Float.MAX_VALUE;
break;
}
return true;
}
/**
* 触发事件之后重置
*/
private void resetAfterDismiss() {
this.setVisibility(GONE);
text = "";
isArrivedMaxMoved = false;
curRadius = originRadius;
postInvalidate();
}
/**
* 根据移动的距离来刷新原来的圆半径大小
*
* @param distance
*/
private void refreshCurRadiusByMoveDistance(int distance) {
if (distance > maxMoveLength) {
isArrivedMaxMoved = true;
curRadius = 0;
} else {
isArrivedMaxMoved = false;
float calcRadius = (1 - 1f * distance / maxMoveLength) * originRadius;
float maxRadius = ABTextUtil.dip2px(context, 2);
curRadius = (int) Math.max(calcRadius, maxRadius);
// Logger.d(TAG, "[refreshCurRadiusByMoveDistance]curRadius: " + curRadius + ", calcRadius: " + calcRadius + ", maxRadius: " + maxRadius);
}
}
/**
* 改变某控件的高度
*
* @param view
* @param height
*/
private void changeViewHeight(View view, int width, int height) {
ViewGroup.LayoutParams lp = view.getLayoutParams();
if (null == lp) {
lp = originLp;
}
lp.width = width;
lp.height = height;
view.setLayoutParams(lp);
}
/**
* 回滚状态动画
*/
private void startRollBackAnimation(long duration) {
ValueAnimator rollBackAnim = ValueAnimator.ofFloat(curRadius, originRadius);
rollBackAnim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
float value = (float) animation.getAnimatedValue();
curRadius = (int) value;
postInvalidate();
}
});
rollBackAnim.setInterpolator(new BounceInterpolator()); // 反弹效果
rollBackAnim.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
super.onAnimationEnd(animation);
DraggableFlagView.this.clearAnimation();
}
});
rollBackAnim.setDuration(duration);
rollBackAnim.start();
}
/**
* 计算四个坐标的三角边关系
*/
class Triangle {
double deltaX;
double deltaY;
double hypotenuse;
@Override
public String toString() {
return "Triangle{" +
"deltaX=" + deltaX +
", deltaY=" + deltaY +
", hypotenuse=" + hypotenuse +
'}';
}
}
public String getText() {
return text;
}
public void setText(String text) {
this.text = text;
this.setVisibility(VISIBLE);
postInvalidate();
}
}
ABAppUtil和ABTextUtil只用到其中的四个方法,里面的大部分方法都是没有用的。
ABAppUtil:
package com.example.mylastitemmessage;
import android.annotation.TargetApi;
import android.app.Activity;
import android.app.ActivityManager;
import android.app.KeyguardManager;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.graphics.Rect;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.net.Uri;
import android.net.wifi.WifiInfo;
import android.net.wifi.WifiManager;
import android.os.Build;
import android.provider.Settings;
import android.telephony.TelephonyManager;
import android.view.View;
import android.view.ViewTreeObserver;
import android.view.Window;
import android.view.WindowManager;
import android.view.inputmethod.InputMethodManager;
import android.widget.EditText;
import java.io.File;
import java.lang.reflect.Field;
import java.util.List;
import java.util.Properties;
import java.util.Set;
/**
* 当前程序是否后台运行
* 当前手机是否处于睡眠
* 当前网络是否已连接
* 当前网络是否wifi状态
* 安装apk
* 初始化view的高度
* 初始化view的高度后不可见
* 判断是否为手机
* 获取屏幕宽度
* 获取屏幕高度
* 获取设备的IMEI
* 获取设备的mac地址
* 获取当前应用的版本号
* 收集设备信息并以Properties返回
* 收集设备信息并以String返回
* <p>
* Created with IntelliJ IDEA.
* Author: wangjie email:tiantian.china.2@gmail.com
* Date: 13-6-5
* Time: 下午3:14
*/
public class ABAppUtil {
private static final String TAG = ABAppUtil.class.getSimpleName();
/**
* 判断当前应用程序是否后台运行
* 在android5.0以上失效!请使用isApplicationBackground()方法代替!
*
* @param context
* @return
*/
@TargetApi(Build.VERSION_CODES.CUPCAKE)
@Deprecated
public static boolean isBackground(Context context) {
ActivityManager activityManager = (ActivityManager) context
.getSystemService(Context.ACTIVITY_SERVICE);
List<ActivityManager.RunningAppProcessInfo> appProcesses = activityManager
.getRunningAppProcesses();
for (ActivityManager.RunningAppProcessInfo appProcess : appProcesses) {
if (appProcess.processName.equals(context.getPackageName())) {
if (appProcess.importance == ActivityManager.RunningAppProcessInfo.IMPORTANCE_BACKGROUND) {
// Logger.d(TAG, "后台程序: " + appProcess.processName);
return true;
} else {
// Logger.d(TAG, "前台程序: " + appProcess.processName);
return false;
}
}
}
return false;
}
/**
* 判断当前应用程序处于前台还是后台
* 需要添加权限: <uses-permission android:name="android.permission.GET_TASKS" />
*/
public static boolean isApplicationBackground(final Context context) {
ActivityManager am = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
List<ActivityManager.RunningTaskInfo> tasks = am.getRunningTasks(1);
if (!tasks.isEmpty()) {
ComponentName topActivity = tasks.get(0).topActivity;
if (!topActivity.getPackageName().equals(context.getPackageName())) {
// Logger.d(TAG, "isBackground: " + true);
return true;
}
}
// Logger.d(TAG, "isBackground: " + false);
return false;
}
/**
* 判断手机是否处理睡眠
*
* @param context
* @return
*/
public static boolean isSleeping(Context context) {
KeyguardManager kgMgr = (KeyguardManager) context.getSystemService(Context.KEYGUARD_SERVICE);
boolean isSleeping = kgMgr.inKeyguardRestrictedInputMode();
// Logger.d(TAG, isSleeping ? "手机睡眠中.." : "手机未睡眠...");
return isSleeping;
}
/**
* 检查网络是否已连接
*
* @param context
* @return
* @author com.tiantian
*/
public static boolean isOnline(Context context) {
ConnectivityManager manager = (ConnectivityManager) context
.getSystemService(Activity.CONNECTIVITY_SERVICE);
NetworkInfo info = manager.getActiveNetworkInfo();
if (info != null && info.isConnected()) {
return true;
}
return false;
}
/**
* 判断当前是否是wifi状态
*
* @param context
* @return
*/
public static boolean isWifiConnected(Context context) {
ConnectivityManager connectivityManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo wifiNetworkInfo = connectivityManager.getNetworkInfo(ConnectivityManager.TYPE_WIFI);
if (wifiNetworkInfo.isConnected()) {
return true;
}
return false;
}
/**
* 安装apk
*
* @param context
* @param file
*/
public static void installApk(Context context, File file) {
Intent intent = new Intent();
intent.setAction("android.intent.action.VIEW");
intent.addCategory("android.intent.category.DEFAULT");
intent.setType("application/vnd.android.package-archive");
intent.setData(Uri.fromFile(file));
intent.setDataAndType(Uri.fromFile(file), "application/vnd.android.package-archive");
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(intent);
}
/**
* 初始化View的高宽
*
* @param view
*/
@Deprecated
public static void initViewWH(final View view) {
view.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
view.getViewTreeObserver().removeGlobalOnLayoutListener(this);
System.out.println(view + ", width: " + view.getWidth() + "; height: " + view.getHeight());
}
});
}
/**
* 初始化View的高宽并显示不可见
*
* @param view
*/
@Deprecated
public static void initViewWHAndGone(final View view) {
view.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
view.getViewTreeObserver().removeGlobalOnLayoutListener(this);
view.setVisibility(View.GONE);
}
});
}
/**
* 使用Properties来保存设备的信息和错误堆栈信息
*/
private static final String VERSION_NAME = "versionName";
private static final String VERSION_CODE = "versionCode";
private static final String STACK_TRACE = "STACK_TRACE";
/**
* 判断是否为手机
*
* @param context
* @return
* @author wangjie
*/
public static boolean isPhone(Context context) {
TelephonyManager telephony = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
int type = telephony.getPhoneType();
if (type == TelephonyManager.PHONE_TYPE_NONE) {
// Logger.i(TAG, "Current device is Tablet!");
return false;
} else {
// Logger.i(TAG, "Current device is phone!");
return true;
}
}
/**
* 获得设备的屏幕宽度
*
* @param context
* @return
*/
public static int getDeviceWidth(Context context) {
WindowManager manager = (WindowManager) context
.getSystemService(Context.WINDOW_SERVICE);
return manager.getDefaultDisplay().getWidth();
}
/**
* 获得设备的屏幕高度
*
* @param context
* @return
*/
public static int getDeviceHeight(Context context) {
WindowManager manager = (WindowManager) context
.getSystemService(Context.WINDOW_SERVICE);
return manager.getDefaultDisplay().getHeight();
}
/**
* 获取设备id(IMEI)
*
* @param context
* @return
* @author wangjie
*/
@TargetApi(Build.VERSION_CODES.CUPCAKE)
public static String getDeviceIMEI(Context context) {
String deviceId;
TelephonyManager telephony = (TelephonyManager) context
.getSystemService(Context.TELEPHONY_SERVICE);
deviceId = telephony.getDeviceId();
if (deviceId == null) {
deviceId = Settings.Secure.getString(context.getContentResolver(),
Settings.Secure.ANDROID_ID);
}
// Logger.d(TAG, "当前设备IMEI码: " + deviceId);
return deviceId != null ? deviceId : "Unknown";
}
/**
* 获取设备mac地址
*
* @param context
* @return
* @author wangjie
*/
// public static String getMacAddress(Context context) {
// String macAddress;
// WifiManager wifi = (WifiManager) context
// .getSystemService(Context.WIFI_SERVICE);
// WifiInfo info = wifi.getConnectionInfo();
// macAddress = info.getMacAddress();
// Logger.d(TAG, "当前mac地址: " + (null == macAddress ? "null" : macAddress));
// if (null == macAddress) {
// return "";
// }
// macAddress = macAddress.replace(":", "");
// return macAddress;
// }
/**
* 获取当前应用程序的版本号
*
* @return
* @author wangjie
*/
// public static String getAppVersion() {
// String version = "0";
// try {
// Context context = ABApplication.getInstance();
// version = context.getPackageManager().getPackageInfo(context.getPackageName(), 0).versionName;
// } catch (PackageManager.NameNotFoundException e) {
// e.printStackTrace();
// Logger.e(TAG, "getAppVersion", e);
// }
// Logger.d(TAG, "该应用的版本号: " + version);
// return version;
// }
/**
* 收集设备信息
*
* @param context
*/
public static Properties collectDeviceInfo(Context context) {
Properties mDeviceCrashInfo = new Properties();
try {
// Class for retrieving various kinds of information related to the
// application packages that are currently installed on the device.
// You can find this class through getPackageManager().
PackageManager pm = context.getPackageManager();
// getPackageInfo(String packageName, int flags)
// Retrieve overall information about an application package that is installed on the system.
// public static final int GET_ACTIVITIES
// Since: API Level 1 PackageInfo flag: return information about activities in the package in activities.
PackageInfo pi = pm.getPackageInfo(context.getPackageName(), PackageManager.GET_ACTIVITIES);
if (pi != null) {
// public String versionName The version name of this package,
// as specified by the <manifest> tag's versionName attribute.
mDeviceCrashInfo.put(VERSION_NAME, pi.versionName == null ? "not set" : pi.versionName);
// public int versionCode The version number of this package,
// as specified by the <manifest> tag's versionCode attribute.
mDeviceCrashInfo.put(VERSION_CODE, pi.versionCode);
}
} catch (PackageManager.NameNotFoundException e) {
// Logger.e(TAG, "Error while collect package info", e);
}
// 使用反射来收集设备信息.在Build类中包含各种设备信息,
// 例如: 系统版本号,设备生产商 等帮助调试程序的有用信息
// 返回 Field 对象的一个数组,这些对象反映此 Class 对象所表示的类或接口所声明的所有字段
Field[] fields = Build.class.getDeclaredFields();
for (Field field : fields) {
try {
// setAccessible(boolean flag)
// 将此对象的 accessible 标志设置为指示的布尔值。
// 通过设置Accessible属性为true,才能对私有变量进行访问,不然会得到一个IllegalAccessException的异常
field.setAccessible(true);
mDeviceCrashInfo.put(field.getName(), field.get(null));
// if (DEBUG) {
// Logger.d(TAG, field.getName() + " : " + field.get(null));
// }
} catch (Exception e) {
// Logger.e(TAG, "Error while collect crash info", e);
}
}
return mDeviceCrashInfo;
}
/**
* 收集设备信息
*
* @param context
* @return
*/
public static String collectDeviceInfoStr(Context context) {
Properties prop = collectDeviceInfo(context);
Set deviceInfos = prop.keySet();
StringBuilder deviceInfoStr = new StringBuilder("{\n");
for (Object item : deviceInfos) {
deviceInfoStr.append("\t\t\t").append(item).append(":").append(prop.get(item)).append(", \n");
}
deviceInfoStr.append("}");
return deviceInfoStr.toString();
}
/**
* 是否有SDCard
*
* @return
*/
public static boolean haveSDCard() {
return android.os.Environment.getExternalStorageState().equals(
android.os.Environment.MEDIA_MOUNTED);
}
/**
* 隐藏软键盘
*/
@TargetApi(Build.VERSION_CODES.CUPCAKE)
public static void hideSoftInput(Context context) {
View view = ((Activity) context).getWindow().peekDecorView();
if (view != null) {
InputMethodManager inputmanger = (InputMethodManager) context.getSystemService(Context.INPUT_METHOD_SERVICE);
inputmanger.hideSoftInputFromWindow(view.getWindowToken(), 0);
}
}
/**
* 隐藏软键盘
*/
@TargetApi(Build.VERSION_CODES.CUPCAKE)
public static void hideSoftInput(Context context, EditText edit) {
edit.clearFocus();
InputMethodManager inputmanger = (InputMethodManager) context.getSystemService(Context.INPUT_METHOD_SERVICE);
inputmanger.hideSoftInputFromWindow(edit.getWindowToken(), 0);
}
/**
* 显示软键盘
*/
@TargetApi(Build.VERSION_CODES.CUPCAKE)
public static void showSoftInput(Context context, EditText edit) {
edit.setFocusable(true);
edit.setFocusableInTouchMode(true);
edit.requestFocus();
InputMethodManager inputManager = (InputMethodManager) context.getSystemService(Context.INPUT_METHOD_SERVICE);
inputManager.showSoftInput(edit, 0);
}
@TargetApi(Build.VERSION_CODES.CUPCAKE)
public static void toggleSoftInput(Context context, EditText edit) {
edit.setFocusable(true);
edit.setFocusableInTouchMode(true);
edit.requestFocus();
InputMethodManager inputManager = (InputMethodManager) context.getSystemService(Context.INPUT_METHOD_SERVICE);
inputManager.toggleSoftInput(InputMethodManager.SHOW_FORCED, 0);
}
/**
* 回到home,后台运行
*
* @param context
*/
public static void goHome(Context context) {
// Logger.d(TAG, "返回键回到HOME,程序后台运行...");
Intent mHomeIntent = new Intent(Intent.ACTION_MAIN);
mHomeIntent.addCategory(Intent.CATEGORY_HOME);
mHomeIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK
| Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
context.startActivity(mHomeIntent);
}
/**
* 获取状态栏高度
*
* @param activity
* @return
*/
@TargetApi(Build.VERSION_CODES.CUPCAKE)
public static int getStatusBarHeight(Activity activity) {
Rect frame = new Rect();
activity.getWindow().getDecorView().getWindowVisibleDisplayFrame(frame);
return frame.top;
}
/**
* 获取状态栏高度+标题栏高度
*
* @param activity
* @return
*/
public static int getTopBarHeight(Activity activity) {
return activity.getWindow().findViewById(Window.ID_ANDROID_CONTENT).getTop();
}
/**
* 获取网络类型
*
* @return
*/
public static int getNetworkType(Context context) {
TelephonyManager telephonyManager = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
return telephonyManager.getNetworkType();
}
/**
* MCC+MNC代码 (SIM卡运营商国家代码和运营商网络代码)
* 仅当用户已在网络注册时有效, CDMA 可能会无效
*
* @return (中国移动:46000 46002, 中国联通:46001,中国电信:46003)
*/
public static String getNetworkOperator(Context context) {
TelephonyManager telephonyManager = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
return telephonyManager.getNetworkOperator();
}
/**
* 返回移动网络运营商的名字(例:中国联通、中国移动、中国电信)
* 仅当用户已在网络注册时有效, CDMA 可能会无效
*
* @return
*/
public static String getNetworkOperatorName(Context context) {
TelephonyManager telephonyManager = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
return telephonyManager.getNetworkOperatorName();
}
/**
* 返回移动终端类型
* PHONE_TYPE_NONE :0手机制式未知
* PHONE_TYPE_GSM :1手机制式为GSM,移动和联通
* PHONE_TYPE_CDMA :2手机制式为CDMA,电信
* PHONE_TYPE_SIP:3
*
* @return
*/
public static int getPhoneType(Context context) {
TelephonyManager telephonyManager = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
return telephonyManager.getPhoneType();
}
/**
* 在中国,联通的3G为UMTS或HSDPA,移动和联通的2G为GPRS或EGDE,电信的2G为CDMA,电信的3G为EVDO
*
* @return 2G、3G、4G、未知四种状态
*/
// public static int getNetWorkClass(Context context) {
// TelephonyManager telephonyManager = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
//
// switch (telephonyManager.getNetworkType()) {
// case TelephonyManager.NETWORK_TYPE_GPRS:
// case TelephonyManager.NETWORK_TYPE_EDGE:
// case TelephonyManager.NETWORK_TYPE_CDMA:
// case TelephonyManager.NETWORK_TYPE_1xRTT:
// case TelephonyManager.NETWORK_TYPE_IDEN:
// return Constants.NETWORK_CLASS_2_G;
//
// case TelephonyManager.NETWORK_TYPE_UMTS:
// case TelephonyManager.NETWORK_TYPE_EVDO_0:
// case TelephonyManager.NETWORK_TYPE_EVDO_A:
// case TelephonyManager.NETWORK_TYPE_HSDPA:
// case TelephonyManager.NETWORK_TYPE_HSUPA:
// case TelephonyManager.NETWORK_TYPE_HSPA:
// case TelephonyManager.NETWORK_TYPE_EVDO_B:
// case TelephonyManager.NETWORK_TYPE_EHRPD:
// case TelephonyManager.NETWORK_TYPE_HSPAP:
// return Constants.NETWORK_CLASS_3_G;
//
// case TelephonyManager.NETWORK_TYPE_LTE:
// return Constants.NETWORK_CLASS_4_G;
//
// default:
// return Constants.NETWORK_CLASS_UNKNOWN;
// }
// }
/**
* 返回状态:当前的网络链接状态
* 0:其他
* 1:WIFI
* 2:2G
* 3:3G
* 4:4G
*
* @return 没有网络,2G,3G,4G,WIFI
*/
// public static int getNetWorkStatus(Context context) {
// int netWorkType = Constants.NETWORK_CLASS_UNKNOWN;
//
// ConnectivityManager connectivityManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
// NetworkInfo networkInfo = connectivityManager.getActiveNetworkInfo();
//
// if (networkInfo != null && networkInfo.isConnected()) {
// int type = networkInfo.getType();
//
// if (type == ConnectivityManager.TYPE_WIFI) {
// netWorkType = Constants.NETWORK_WIFI;
// } else if (type == ConnectivityManager.TYPE_MOBILE) {
// netWorkType = getNetWorkClass(context);
// }
// }
//
// return netWorkType;
// }
/**
* Check if this device has a camera
*/
public static boolean checkCameraHardware(Context context) {
return context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA);
}
// public static String getIp(Context context){
// WifiManager wm=(WifiManager)context.getSystemService(Context.WIFI_SERVICE);
// //检查Wifi状态
// if(!wm.isWifiEnabled())
// wm.setWifiEnabled(true);
// WifiInfo wi=wm.getConnectionInfo();
// //获取32位整型IP地址
// int ipAdd=wi.getIpAddress();
// //把整型地址转换成“*.*.*.*”地址
// return intToIp(ipAdd);
// }
private static String intToIp(int i) {
return (i & 0xFF ) + "." +
((i >> 8 ) & 0xFF) + "." +
((i >> 16 ) & 0xFF) + "." +
( i >> 24 & 0xFF) ;
}
}
ABTextUtil:
package com.example.mylastitemmessage;
import android.content.Context;
import android.graphics.drawable.Drawable;
import android.text.Spannable;
import android.text.SpannableString;
import android.text.style.ImageSpan;
import android.util.DisplayMetrics;
import java.io.*;
import java.util.Collection;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.zip.GZIPInputStream;
import java.util.zip.GZIPOutputStream;
/**
* Created with IntelliJ IDEA.
* Author: wangjie email:tiantian.china.2@gmail.com
* Date: 14-3-28
* Time: 上午10:57
*/
public class ABTextUtil {
public static final String TAG = ABTextUtil.class.getSimpleName();
/**
* 获得字体的缩放密度
*
* @param context
* @return
*/
public static float getScaledDensity(Context context) {
DisplayMetrics dm = context.getResources().getDisplayMetrics();
return dm.scaledDensity;
}
/**
* 根据手机的分辨率从 dp 的单位 转成为 px(像素)
*/
public static int dip2px(Context context, float dpValue) {
final float scale = context.getResources().getDisplayMetrics().density;
return (int) (dpValue * scale + 0.5f);
}
/**
* 根据手机的分辨率从 px(像素) 的单位 转成为 dp
*/
public static int px2dip(Context context, float pxValue) {
final float scale = context.getResources().getDisplayMetrics().density;
return (int) (pxValue / scale + 0.5f);
}
/**
* 将px值转换为sp值,保证文字大小不变
*
* @param pxValue
* @return
*/
public static int px2sp(Context context, float pxValue) {
final float fontScale = context.getResources().getDisplayMetrics().scaledDensity;
return (int) (pxValue / fontScale + 0.5f);
}
/**
* 将sp值转换为px值,保证文字大小不变
*
* @param spValue
* @return
*/
public static int sp2px(Context context, float spValue) {
final float fontScale = context.getResources().getDisplayMetrics().scaledDensity;
return (int) (spValue * fontScale + 0.5f);
}
/**
* *************************************************************
*/
public static boolean isEmpty(Collection collection) {
return null == collection || collection.isEmpty();
}
public static boolean isEmpty(Map map) {
return null == map || map.isEmpty();
}
public static boolean isEmpty(Object[] objs) {
return null == objs || objs.length <= 0;
}
public static boolean isEmpty(int[] objs) {
return null == objs || objs.length <= 0;
}
public static boolean isEmpty(CharSequence charSequence) {
return null == charSequence || charSequence.length() <= 0;
}
public static boolean isBlank(CharSequence charSequence) {
return null == charSequence || charSequence.toString().trim().length() <= 0;
}
public static boolean isLeast(Object[] objs, int count) {
return null != objs && objs.length >= count;
}
public static boolean isLeast(int[] objs, int count) {
return null != objs && objs.length >= count;
}
public static boolean isEquals(Object a, Object b) {
return (a == null) ? (b == null) : a.equals(b);
}
public static String trim(CharSequence charSequence) {
return null == charSequence ? null : charSequence.toString().trim();
}
/**
* 摘取里面第一个不为null的字符串
*
* @param options
* @return
*/
public static String pickFirstNotNull(CharSequence... options) {
if (isEmpty(options)) {
return null;
}
String result = null;
for (CharSequence cs : options) {
if (null != cs) {
result = cs.toString();
break;
}
}
return result;
}
/**
* 摘取里面第一个不为null的字符串
*
* @param options
* @return
*/
@SafeVarargs
public static <T> T pickFirstNotNull(Class<T> clazz, T... options) {
if (isEmpty(options)) {
return null;
}
T result = null;
for (T obj : options) {
if (null != obj) {
result = obj;
break;
}
}
return result;
}
/**
* 替换文本为图片
*
* @param charSequence
* @param regPattern
* @param drawable
* @return
*/
public static SpannableString replaceImageSpan(CharSequence charSequence, String regPattern, Drawable drawable) {
SpannableString ss = charSequence instanceof SpannableString ? (SpannableString) charSequence : new SpannableString(charSequence);
try {
ImageSpan is = new ImageSpan(drawable);
Pattern pattern = Pattern.compile(regPattern);
Matcher matcher = pattern.matcher(ss);
while (matcher.find()) {
String key = matcher.group();
ss.setSpan(is, matcher.start(), matcher.start() + key.length(), Spannable.SPAN_INCLUSIVE_EXCLUSIVE);
}
} catch (Exception ex) {
// Logger.e(TAG, ex);
}
return ss;
}
/**
* 压缩字符串到Zip
*
* @param str
* @return 压缩后字符串
* @throws IOException
*/
public static String compress(String str) throws IOException {
if (str == null || str.length() == 0) {
return str;
}
ByteArrayOutputStream out = new ByteArrayOutputStream();
GZIPOutputStream gzip = new GZIPOutputStream(out);
gzip.write(str.getBytes());
gzip.close();
return out.toString("ISO-8859-1");
}
/**
* 解压Zip字符串
*
* @param str
* @return 解压后字符串
* @throws IOException
*/
public static String uncompress(String str) throws IOException {
if (str == null || str.length() == 0) {
return str;
}
ByteArrayInputStream in = new ByteArrayInputStream(str
.getBytes("UTF-8"));
return uncompress(in);
}
/**
* 解压Zip字符串
*
* @param inputStream
* @return 解压后字符串
* @throws IOException
*/
public static String uncompress(InputStream inputStream) throws IOException {
if (inputStream == null) {
return null;
}
ByteArrayOutputStream out = new ByteArrayOutputStream();
GZIPInputStream gunzip = new GZIPInputStream(inputStream);
byte[] buffer = new byte[256];
int n;
while ((n = gunzip.read(buffer)) >= 0) {
out.write(buffer, 0, n);
}
return out.toString();
}
/**
* InputStream convert to string
*
* @param in
* @return
* @throws IOException
*/
public static String inputStream2String(InputStream in) throws IOException {
StringBuffer out = new StringBuffer();
byte[] b = new byte[4096];
for (int n; (n = in.read(b)) != -1; ) {
out.append(new String(b, 0, n));
}
return out.toString();
}
// /**
// * 解压Gzip获取
// *
// * @param is
// * @return
// */
// public static String inputStream2StringFromGZIP(InputStream is) {
// StringBuilder resultSb = new StringBuilder();
// BufferedInputStream bis = null;
// InputStreamReader reader = null;
// try {
// bis = new BufferedInputStream(is);
// bis.mark(2);
// // 取前两个字节
// byte[] header = new byte[2];
// int result = bis.read(header);
// // reset输入流到开始位置
// bis.reset();
// // 判断是否是GZIP格式
// int headerData = getShort(header);
// // Gzip流的前两个字节是0x1f8b
// if (result != -1 && headerData == 0x1f8b) {
// is = new GZIPInputStream(bis);
// } else {
// is = bis;
// }
// reader = new InputStreamReader(is, "utf-8");
// char[] data = new char[100];
// int readSize;
// while ((readSize = reader.read(data)) > 0) {
// resultSb.append(data, 0, readSize);
// }
// } catch (Exception e) {
// Logger.e(TAG, e);
// } finally {
// ABIOUtil.closeIO(is, bis, reader);
// }
// return resultSb.toString();
// }
private static int getShort(byte[] data) {
return (int) ((data[0] << 8) | data[1] & 0xFF);
}
public static String getExceptionStackTrace(Throwable throwable) {
if (null == throwable) {
return "null";
}
StringBuilder sb = new StringBuilder(throwable.getMessage()).append("\n");
StackTraceElement[] elements = throwable.getStackTrace();
for (StackTraceElement element : elements) {
sb.append(element.toString()).append("\r\n");
}
return sb.toString();
}
}
attrs文件放到values中:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="DraggableFlagView">
<attr name="DraggableFlagView_color" format="color"/>
</declare-styleable>
</resources>
main:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:dfv="http://schemas.android.com/apk/res-auto"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<View android:layout_width="match_parent" android:layout_height="match_parent"
android:background="#aabbcc"
/>
<Button
android:id="@+id/main_btn"
android:layout_width="match_parent" android:layout_height="48dp"
android:layout_alignParentBottom="true"
android:background="#cc000000"
android:textColor="@android:color/white"
android:textSize="20sp"
android:text="click me! "
>
</Button>
<com.example.mylastitemmessage.DraggableFlagView
android:id="@+id/main_dfv"
android:layout_width="20dp"
android:layout_height="20dp"
android:layout_alignParentBottom="true"
android:layout_margin="15dp"
dfv:DraggableFlagView_color="#00ff30"
/>
</RelativeLayout>