Android_WindowManager_实现类似360流量悬浮框

本博文为子墨原创,转载请注明出处!
http://blog.csdn.net/zimo2013/article/details/17054673

1.示意图

Android_WindowManager_实现类似360流量悬浮框_第1张图片              Android_WindowManager_实现类似360流量悬浮框_第2张图片

2.过程实现

这里主要用到WindowManager类,通过WindowManager的addView(View view,  WindowManager.LayoutParams params)方法可以在窗体中添加view对象,如果希望浮动窗体随手指一块移动,应该修改params参数并通过windowManager对象的updateViewLayout()方法完成更新,并配合service!对于WindowManager.LayoutParams这里不做介绍,不了解的朋友可以网上查~

<!-- 浮动窗体 需申请权限 -->
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />

/**
 * 
 * @author zimo2013
 * @see http://blog.csdn.net/zimo2013
 *
 */
public class MyService extends Service {

	private MyWindowManager windowManager;
	/*
	 * 这里使用线程池,比如访问网络数据的实时更新,主要完成于悬浮框的通信,可根据需要实现,这里并没有实现
	 */
	private ScheduledExecutorService threadPool;

	@Override
	public void onCreate() {
		super.onCreate();
	}

	@Override
	public IBinder onBind(Intent intent) {
		return null;
	}

	@Override
	public int onStartCommand(Intent intent, int flags, int startId) {
		if (windowManager == null) {
			windowManager = MyWindowManager
					.getInstance(getApplicationContext());
		}

		if (threadPool == null) {
			threadPool = Executors.newScheduledThreadPool(1);
			threadPool.scheduleAtFixedRate(command, 0, 1, TimeUnit.SECONDS);
		}
		//开启悬浮框
		windowManager.show();
		return super.onStartCommand(intent, flags, startId);
	}
	private Runnable command = new Runnable() {
		@Override
		public void run() {
			// 在该方法中,定时更新ui,比如访问网络数据的实时更新,主要完成于悬浮框的通信,这里暂不实现
			System.out.println("run()");
			
		}
	};

	public void onDestroy() {
		super.onDestroy();

		if (threadPool != null) {
			threadPool.shutdown();
			threadPool = null;
		}
	}
}
/**
 * 单例设计
 * 
 * @author zimo2013
 * @see http://blog.csdn.net/zimo2013
 * 
 */
public class MyWindowManager {

	private static MyWindowManager manager;

	private MyWindowManager() {
	}

	private static WindowManager winManager;
	private static Context context;
	private LayoutParams params;
	private LayoutParams paramsContent;
	/**
	 * 显示的浮动窗体
	 */
	private FloatView floatView;
	/**
	 * 点击浮动窗体后的详细信息
	 */
	private FloatContentView floatContentView;

	// 屏幕的尺寸
	private static int displayWidth;
	private static int displayHeight;

	/**
	 * @param context
	 *            ApplicationContext
	 * @return
	 */
	public static synchronized MyWindowManager getInstance(Context context) {
		if (manager == null) {
			MyWindowManager.context = context;
			winManager = (WindowManager) context
					.getSystemService(Context.WINDOW_SERVICE);
			displayWidth = winManager.getDefaultDisplay().getWidth();
			displayHeight = winManager.getDefaultDisplay().getHeight();

			manager = new MyWindowManager();
		}
		return manager;
	}

	/**
	 * 显示悬浮框
	 */
	public void show() {
		floatView = getView();
		if (floatView.getParent() == null) {
			winManager.addView(floatView, params);
		}
	}

	/**
	 * 点击悬浮框后的显示的实时详细流量信息
	 */
	public void showContent() {
		winManager.addView(getContentView(), paramsContent);

		// 先移除悬浮框
		winManager.removeView(floatView);
		floatView = null;
	}

	// 移动悬浮框
	public void move(View view, int delatX, int deltaY) {
		if (view == floatView) {
			params.x += delatX;
			params.y += deltaY;
			// 更新floatView
			winManager.updateViewLayout(view, params);
		}
	}

	/**
	 * 移除悬浮框
	 */
	public void dismiss() {
		winManager.removeView(floatContentView);
		floatContentView = null;
	}

	public void back() {
		winManager.addView(getView(), params);

		winManager.removeView(floatContentView);
		floatContentView = null;
	}

	/**
	 * 是否实时更新流量数据,主要用于流量悬浮框是否实时更新流量数据
	 * 
	 * @return
	 */
	public boolean isUpdate() {
		if (floatContentView == null) {
			return false;
		}
		return true;
	}

	/**
	 * 得到悬浮框view
	 * 
	 * @return
	 */
	public FloatView getView() {
		if (floatView == null) {
			floatView = new FloatView(context);
		}
		if (params == null) {
			params = new LayoutParams();
			params.type = LayoutParams.TYPE_PHONE;
			params.format = PixelFormat.RGBA_8888;
			params.flags = LayoutParams.FLAG_NOT_TOUCH_MODAL
					| LayoutParams.FLAG_NOT_FOCUSABLE;
			params.gravity = Gravity.LEFT | Gravity.TOP;

			// 须指定宽度高度信息
			params.width = floatView.mWidth;
			params.height = floatView.mHeight;

			params.x = displayWidth - floatView.mWidth;
			params.y = displayHeight / 2;
		}
		return floatView;
	}

	/**
	 * 得到实时流量悬浮框view
	 * 
	 * @return
	 */
	public View getContentView() {
		if (floatContentView == null) {
			floatContentView = new FloatContentView(context);
		}
		if (paramsContent == null) {
			paramsContent = new LayoutParams();
			paramsContent.type = LayoutParams.TYPE_PHONE;
			paramsContent.format = PixelFormat.RGBA_8888;
			paramsContent.flags = LayoutParams.FLAG_NOT_TOUCH_MODAL
					| LayoutParams.FLAG_NOT_FOCUSABLE;
			paramsContent.gravity = Gravity.LEFT | Gravity.TOP;

			// 须指定宽度高度信息
			paramsContent.width = floatContentView.mWidth;
			paramsContent.height = floatContentView.mHeight;

			paramsContent.x = (displayWidth - floatContentView.mWidth) / 2;
			paramsContent.y = (displayHeight - floatContentView.mHeight) / 2;
		}
		return floatContentView;
	}
}
public class FloatView extends LinearLayout {
	private TextView tvInfo;
	private MyWindowManager manager;

	public int mWidth;
	public int mHeight;

	private int preX;
	private int preY;
	private int x;
	private int y;
	private boolean isMove;

	public FloatView(Context context) {
		this(context, null);
	}

	public FloatView(Context context, AttributeSet attrs) {
		super(context, attrs);
		// 填充布局,并添加至
		LayoutInflater.from(context).inflate(R.layout.float_view, this);
		tvInfo = (TextView) findViewById(R.id.tv_info);

		//宽高
		mWidth = tvInfo.getLayoutParams().width;
		mHeight = tvInfo.getLayoutParams().height;

		manager = MyWindowManager.getInstance(context);
	}

	@Override
	public boolean onTouchEvent(MotionEvent event) {
		switch (event.getAction()) {
		case MotionEvent.ACTION_DOWN:
			preX = (int) event.getRawX();
			preY = (int) event.getRawY();
			isMove = false;
			break;
		case MotionEvent.ACTION_MOVE:
			x = (int) event.getRawX();
			y = (int) event.getRawY();
			manager.move(this, x - preX, y - preY);
			isMove = true;
			preX = x;
			preY = y;
			break;
		case MotionEvent.ACTION_UP:
			if (!isMove) {//是否是移动,主要是区分click
				//显示悬浮框详细流量信息
				manager.showContent();
			}
			break;
		}
		return super.onTouchEvent(event);
	}
}
public class FloatContentView extends LinearLayout implements OnClickListener {

	public int mWidth;
	public int mHeight;
	private MyWindowManager manager;
	private PackageManager pkgManager;
	private LayoutInflater inflater;
	private TrafficAdapter adapter;

	private Button btCLose;
	private Button btBack;
	private ListView listView;

	public FloatContentView(Context context) {
		this(context, null);
	}

	public FloatContentView(Context context, AttributeSet attrs) {
		super(context, attrs);
		pkgManager = context.getPackageManager();
		// 填充布局,并添加至
		inflater = LayoutInflater.from(context);

		inflater.inflate(R.layout.float_content_view, this);
		manager = MyWindowManager.getInstance(context);

		ViewGroup.LayoutParams params = findViewById(R.id.content)
				.getLayoutParams();
		mWidth = params.width;
		mHeight = params.height;

		btCLose = (Button) findViewById(R.id.bt_close);
		btBack = (Button) findViewById(R.id.bt_back);
		listView = (ListView) findViewById(R.id.list);

		btCLose.setOnClickListener(this);
		btBack.setOnClickListener(this);

		adapter = new TrafficAdapter();
		listView.setAdapter(adapter);
		//消息,主要完成流量的实时更新
		handler.sendEmptyMessage(0);
	}

	// 主要用于实时更新
	private Handler handler = new Handler() {
		public void handleMessage(android.os.Message msg) {
			// 更新流信息
			if (manager.isUpdate()) {
				adapter.notifyDataSetChanged();
				handler.sendEmptyMessageDelayed(0, 2 * 1000);
			}
		}
	};

	@Override
	public void onClick(View v) {
		if (v == btCLose) {
			manager.dismiss();
		} else if (v == btBack) {
			manager.back();
		}
	}

	private class TrafficAdapter extends BaseAdapter {

		private List<ResolveInfo> infos;

		TrafficAdapter() {
			Intent intent = new Intent();
			intent.setAction(Intent.ACTION_MAIN);
			intent.addCategory(Intent.CATEGORY_LAUNCHER);
			//根据意图,查询得到与之对应的list信息
			infos = pkgManager.queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY);
		}

		@Override
		public int getCount() {
			return infos.size();
		}

		@Override
		public Object getItem(int position) {
			return infos.get(position);
		}

		@Override
		public long getItemId(int position) {
			return position;
		}

		@Override
		public View getView(int position, View convertView, ViewGroup parent) {
			if (convertView == null) {
				convertView = inflater.inflate(R.layout.item, null);
				convertView.setTag(new ViewHolder(convertView));
			}
			ViewHolder holder = (ViewHolder) convertView.getTag();

			ResolveInfo info = infos.get(position);
			holder.tvPkgName.setText(info.loadLabel(pkgManager).toString());
			try {
				//得到uid
				int uid = pkgManager.getPackageInfo(info.activityInfo.packageName,
						0).applicationInfo.uid;
				//TrafficStats查询具体流量数据
				holder.tvRcvSize.setText(SizeFormaterUtil.getDataSize(TrafficStats
						.getUidRxBytes(uid)));
				holder.tvSndSize.setText(SizeFormaterUtil.getDataSize(TrafficStats
						.getUidTxBytes(uid)));
			} catch (NameNotFoundException e) {
				e.printStackTrace();
			}
			return convertView;
		}

	}

	private class ViewHolder {
		TextView tvPkgName;
		TextView tvRcvSize;
		TextView tvSndSize;

		public ViewHolder(View view) {
			tvPkgName = (TextView) view.findViewById(R.id.tv_name);
			tvRcvSize = (TextView) view.findViewById(R.id.tv_rcv);
			tvSndSize = (TextView) view.findViewById(R.id.tv_snd);
		}
	}

}
源码下载>>

你可能感兴趣的:(android,trafficstats,windowmanager,流量)