1,用途:
显示在界面底部提示后台的操作进度.比如下载进度.
2,原理:
(1)将提示界面以TYPE_SYSTEM_ALERT,TYPE_SYSTEM_OVERLAY的形式加入到WindowManager中,从而实现全局的悬浮窗口.
(2)创建一个Activity作为所有activity的基类,在onResume时显示悬浮窗口,在onPause里移除悬浮窗口.这样当应用退出或被其他应用覆盖时,悬浮窗口会消失,从而实现悬浮窗口被自己的应用拥有的效果.
3,不足:
界面切换时会出现短暂的消失.
4,代码简析:
主要的方法:
(1) public static FloatingBargetInstance(Context c)
本类被设计成单例模式,也就是只有一个实例,方便管理.
(2) protected void onDraw(Canvascanvas)
绘制界面
(3) public void show()
显示悬浮框
(4) public void dismiss()
隐藏悬浮框
(5) public static booleanneedFloatingBar()
是否要显示
5,截图
6,代码
import java.util.List;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Paint.FontMetrics;
import android.graphics.PixelFormat;
import android.graphics.Rect;
import android.graphics.Typeface;
import android.util.Log;
import android.view.Gravity;
import android.view.WindowManager;
import android.view.WindowManager.LayoutParams;
import android.widget.TextView;
public class FloatingBar extends TextView
{
private final static String TAG = "FloatingBar";
private String mText;
private int mTextSize;
private int mBarHeight;
private int mBarWidth;
private int mIconPadding;
private Bitmap mIcon;
private static Context mContext;
private Paint mPaint;
private Rect mIconSrcRect;
private Rect mIconDestRect;
private Rect mBgSrcRect;
private Rect mBgDestRect;
private float mTextStartX;
private float mTextStartY;
private static FloatingBar mInstance = null;
private Bitmap mBgBmp = null;
public static FloatingBar getInstance(Context c)
{
if (mInstance == null)
{
mInstance = new FloatingBar(c, R.drawable.ic_launcher, "I am a floating bar");
}
return mInstance;
}
private WindowManager mWindowManager;
/**
* <创建进度提示框>
* <进度框显示在屏幕最下方,由应用图标和进度信息组成。>
* @param context 上下文
* @param resId 应用图标资源id
* @param text 下载或安装进度信息
*/
public FloatingBar(Context context, int resId, String text)
{
super(context);
mContext = context;
mText = text;
mIcon = BitmapFactory.decodeResource(mContext.getResources(), resId);
updateIconInfo();
}
/**
* <创建进度提示框>
* <进度框显示在屏幕最下方,由应用图标和进度信息组成。>
* @param context 上下文
* @param appIcon 应用图标位图资源
* @param text 下载或安装进度信息
*/
public FloatingBar(Context context, Bitmap appIcon, String text)
{
super(context);
mContext = context;
mText = text;
mIcon = appIcon;
updateIconInfo();
}
/**
* <设置应用图标>
* @param drawable 应用图标资源id
* @see [类、类#方法、类#成员]
*/
public void setDrawable(int drawable)
{
mIcon = BitmapFactory.decodeResource(mContext.getResources(), drawable);
updateIconInfo();
invalidate();
}
/**
* <设置应用图标>
* @param appIcon 应用图标位图资源
* @see [类、类#方法、类#成员]
*/
public void setDrawable(Bitmap appIcon)
{
mIcon = appIcon;
updateIconInfo();
invalidate();
}
/**
* <设置进度信息>
* @param text 下载、安装进度信息
* @see [类、类#方法、类#成员]
*/
public void setMsg(String text)
{
this.mText = text;
invalidate();
}
/**
* <设置进度框高度>
* @param h 进度框高度
* @see [类、类#方法、类#成员]
*/
public void setBarHeight(int h)
{
mBarHeight = h;
invalidate();
}
/**
* <设置进度信息字体大小>
* @param size 字体大小
* @see [类、类#方法、类#成员]
*/
public void setMsmgTextSize(int size)
{
mTextSize = size;
mPaint.setTextSize(size);
invalidate();
}
@Override
protected void onDraw(Canvas canvas)
{
// TODO Draw item on the floating bar
super.onDraw(canvas);
canvas.drawBitmap(mBgBmp, mBgSrcRect, mBgDestRect, mPaint);
canvas.drawBitmap(mIcon, mIconSrcRect, mIconDestRect, mPaint);
canvas.drawText(mText, mTextStartX, mTextStartY, mPaint);
}
/**
* <显示进度框>
* <在调用dismiss方法移除进度框之前,进度框将一直显示在屏幕最下方。>
* @see [类、类#方法、类#成员]
*/
public void show()
{
if (!isShown())
{
WindowManager.LayoutParams params = new WindowManager.LayoutParams();
params.type = WindowManager.LayoutParams.TYPE_SYSTEM_ALERT | WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY;
params.flags = LayoutParams.FLAG_NOT_TOUCH_MODAL | LayoutParams.FLAG_NOT_FOCUSABLE;
params.width = WindowManager.LayoutParams.FILL_PARENT;
params.height = mBarHeight;
params.alpha = 80;
params.format = PixelFormat.RGBA_8888;
params.gravity = Gravity.LEFT | Gravity.BOTTOM;
params.x = 0;
params.y = 0;
this.setBackgroundColor(Color.BLACK);
mWindowManager.addView(this, params);
}
}
/**
* <移除进度框>
* @see [类、类#方法、类#成员]
*/
public void dismiss()
{
if (this.isShown())
{
mWindowManager.removeView(this);
}
}
/**
* <在更新应用图标后重新计算关于位图的参数>
* @see [类、类#方法、类#成员]
*/
private void updateIconInfo()
{
mPaint = new Paint();
mPaint.setColor(Color.WHITE);
mPaint.setTextSize(mTextSize);
mPaint.setTypeface(Typeface.DEFAULT_BOLD);
mWindowManager =
(WindowManager)getContext().getApplicationContext().getSystemService(getContext().WINDOW_SERVICE);
mBarWidth = mWindowManager.getDefaultDisplay().getWidth();
mBarHeight = 65;
mTextSize = 30;
mIconPadding = 10;
float textW = mPaint.measureText(mText);
FontMetrics fm = mPaint.getFontMetrics();
float textH = fm.descent - fm.ascent;
Log.d(TAG, "archer text height = " + textH + " text=" + mText);
float iconW = mBarHeight - 2 * mIconPadding;
float iconStartX = (mBarWidth - mBarHeight - textW) / 2;
float iconStartY = mIconPadding;
mTextStartX = iconStartX + iconW + mIconPadding;
mTextStartY = (mBarHeight + textH) / 2; // The position of the bottom of text.
mIconSrcRect = new Rect(0, 0, mIcon.getWidth(), mIcon.getHeight());
mIconDestRect =
new Rect((int)iconStartX, (int)iconStartY, (int)(iconStartX + iconW), (int)(iconStartY + iconW));
mBgBmp = BitmapFactory.decodeResource(mContext.getResources(), R.drawable.app_detail_download_install_bg);
mBgSrcRect = new Rect(0, 0, mBgBmp.getWidth(), mBgBmp.getHeight());
mBgDestRect = new Rect(0, 0, mBarWidth, mBarHeight);
}
/**
* 判断当前是否需要进度框。
* @return true 需要进度框 ;false 不需要进度框。
*/
public static boolean needFloatingBar()
{
// return
}
}
定义FloatingBarActivity,作为其他activity的基类
public class FloatingBarActivity extends Activity implements DownloadStateListener
{
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
}
@Override
protected void onPause()
{
super.onPause();
FloatingBar.getInstance(this).dismiss();
}
@Override
protected void onResume()
{
super.onResume();
if (FloatingBar.needFloatingBar())
{
FloatingBar.getInstance(this).show();
}
}
}