Android获取剪切板内容(仿有道复制查词功能)

  支持原创,欢迎转载:http://blog.csdn.net/sonken_0824/article/details/32111257  

Android剪切板(ClipBoardManager)复制的内容,可以粘贴到任何地方,对于一些词典,翻译工具等app具有较高的使用价值。有道词典在3.6版本后就使用到该功能,本文来剖析具体的实现过程。

  首先看一下有道词典的效果图:

   SDK使用说明,API 11以上请导入包:android.content.ClipboardManager。

具体实现流程如下:

   a.开启后台监听服务。

   在服务创建的过程中,启动剪切板,设置内容监听器。

		final ClipboardManager cm = (ClipboardManager) getSystemService(CLIPBOARD_SERVICE);
		cm.addPrimaryClipChangedListener(new OnPrimaryClipChangedListener() {
			@Override
			public void onPrimaryClipChanged() {
				ClipData data = cm.getPrimaryClip();
  				Item item = data.getItemAt(0);
				Intent mIntent = new Intent();
				mIntent.setAction("com.cybertron.dict.ClipBoardReceiver");
				mIntent.putExtra("clipboardvalue", item.getText().toString());
				sendBroadcast(mIntent);
			}
		});

   这里要注意的是API11后,1.获取剪切板内容的操作均在ClipData中;2.这里的监听接口OnPrimaryClipChangedListener,是添加而不是设置。当剪切板内容发生改变时,回调执行onPrimaryClipChanged方法,如果设备有多个这样的监听的话,该方法会执行多次,但影响不大。

   b.获取剪切板内容,启动浮动窗口。

   剪切板内容发生改变后,可以通过发送广播或服务的方式进行数据传输。本文通过的是前者的方式,广播接收器接收到传值后再启动浮动窗口的服务。

   浮动窗口接收传值并显示,并可以拖动。具体实现参考:

public class FloatingWindowService extends Service{

	public static final String OPERATION = "operation";
	public static final int OPERATION_SHOW = 100;
	public static final int OPERATION_HIDE = 101;

	private boolean isAdded = false; // 是否已增加悬浮窗
	
	private static WindowManager wm; 
	
	private static WindowManager.LayoutParams params;
	
	private View floatView;

	private float startX = 0;
	
	private float startY = 0;
	
	private float x;
	
	private float y;
	
	private String copyValue;

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

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

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

	@Override
	public void onStart(Intent intent, int startId) {
		super.onStart(intent, startId);
		if (intent != null) {
			int operation = intent.getIntExtra(OPERATION, OPERATION_SHOW);
			switch (operation) {
			case OPERATION_SHOW:
				if (!isAdded) {
					wm.addView(floatView, params);
					isAdded = true;
				}
				break;
			case OPERATION_HIDE:
				if (isAdded) {
					wm.removeView(floatView);
					isAdded = false;
				}
				break;
			}
			copyValue = intent.getStringExtra("copyValue");
			setupCellView(floatView);
			Log.e(this.getClass().getSimpleName(), "=====copyValue :"+copyValue);
		}
	}
	
	/**
	 * 创建悬浮窗
	 */
	private void createFloatView() {
		LayoutInflater layoutInflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);		
		floatView = layoutInflater.inflate(R.layout.dict_popup_window, null);
		
		wm = (WindowManager) getApplicationContext().getSystemService(Context.WINDOW_SERVICE);
		params = new WindowManager.LayoutParams();

		// 设置window type
		params.type = WindowManager.LayoutParams.TYPE_SYSTEM_ERROR;
		
		/*
		 * 如果设置为params.type = WindowManager.LayoutParams.TYPE_PHONE; 那么优先级会降低一些,
		 * 即拉下通知栏不可见
		 */
		params.format = PixelFormat.RGBA_8888; // 设置图片格式,效果为背景透明

		// 设置Window flag
		params.flags = WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
				| WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
		/*
		 * 下面的flags属性的效果形同“锁定”。 悬浮窗不可触摸,不接受任何事件,同时不影响后面的事件响应。
		 * wmParams.flags=LayoutParams.FLAG_NOT_TOUCH_MODAL |
		 * LayoutParams.FLAG_NOT_FOCUSABLE | LayoutParams.FLAG_NOT_TOUCHABLE;
		 */

		// 设置悬浮窗的长得宽
		params.width = getResources().getDimensionPixelSize(R.dimen.float_width);
		params.height = WindowManager.LayoutParams.WRAP_CONTENT;

		params.gravity = Gravity.LEFT | Gravity.TOP;
		params.x = 0;
		params.y = 0;
		
		// 设置悬浮窗的Touch监听
		floatView.setOnTouchListener(new OnTouchListener() {
			
			@Override
			public boolean onTouch(View v, MotionEvent event) {
				x = event.getRawX();
				y = event.getRawY();
				
				switch(event.getAction()){
				case MotionEvent.ACTION_DOWN:
					startX = event.getX();
					startY = event.getY();
					break;
				case MotionEvent.ACTION_MOVE:					
					params.x = (int)( x - startX);  
					params.y = (int) (y - startY);  
					wm.updateViewLayout(floatView, params);
					break;
				case MotionEvent.ACTION_UP:
					startX = startY = 0;  
					break;
				}
				return true;
			}
		});
		
		wm.addView(floatView, params);
		isAdded = true;
	}

	/**
	 * 设置浮窗view内部子控件
	 * @param rootview
	 */
	private void setupCellView(View rootview) {
		ImageView closedImg = (ImageView) rootview.findViewById(R.id.float_window_closed);
		TextView titleText = (TextView) rootview.findViewById(R.id.float_window_title);
		titleText.setText(copyValue);		
		closedImg.setOnClickListener(new OnClickListener() {
			
			@Override
			public void onClick(View v) {
				if (isAdded) {
					wm.removeView(floatView);
					isAdded = false;
				}
			}
		});
		floatView.setOnClickListener(new OnClickListener() {
			
			@Override
			public void onClick(View v) {
			
			}
		});
	}


}

文章结尾Demo下载地址提供!

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值