1. 程式人生 > >Android獲取剪下板內容(仿有道複製查詞功能)

Android獲取剪下板內容(仿有道複製查詞功能)

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) {
			
			}
		});
	}


}