android有道词典简单开发

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

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

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

具体实现流程如下:

   a.开启后台监听服务。

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

[java]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. final ClipboardManager cm = (ClipboardManager) getSystemService(CLIPBOARD_SERVICE);  
  2. cm.addPrimaryClipChangedListener(new OnPrimaryClipChangedListener() {  
  3.     @Override  
  4.     public void onPrimaryClipChanged() {  
  5.         ClipData data = cm.getPrimaryClip();  
  6.                 Item item = data.getItemAt(0);  
  7.         Intent mIntent = new Intent();  
  8.         mIntent.setAction("com.cybertron.dict.ClipBoardReceiver");  
  9.         mIntent.putExtra("clipboardvalue", item.getText().toString());  
  10.         sendBroadcast(mIntent);  
  11.     }  
  12. });  

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

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

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

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

[java]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. public class FloatingWindowService extends Service{  
  2.   
  3.     public static final String OPERATION = "operation";  
  4.     public static final int OPERATION_SHOW = 100;  
  5.     public static final int OPERATION_HIDE = 101;  
  6.   
  7.     private boolean isAdded = false// 是否已增加悬浮窗  
  8.       
  9.     private static WindowManager wm;   
  10.       
  11.     private static WindowManager.LayoutParams params;  
  12.       
  13.     private View floatView;  
  14.   
  15.     private float startX = 0;  
  16.       
  17.     private float startY = 0;  
  18.       
  19.     private float x;  
  20.       
  21.     private float y;  
  22.       
  23.     private String copyValue;  
  24.   
  25.     @Override  
  26.     public IBinder onBind(Intent intent) {  
  27.         return null;  
  28.     }  
  29.   
  30.     @Override  
  31.     public void onCreate() {  
  32.         super.onCreate();  
  33.         createFloatView();        
  34.     }  
  35.   
  36.     @Override  
  37.     public void onDestroy() {  
  38.         super.onDestroy();  
  39.     }  
  40.   
  41.     @Override  
  42.     public void onStart(Intent intent, int startId) {  
  43.         super.onStart(intent, startId);  
  44.         if (intent != null) {  
  45.             int operation = intent.getIntExtra(OPERATION, OPERATION_SHOW);  
  46.             switch (operation) {  
  47.             case OPERATION_SHOW:  
  48.                 if (!isAdded) {  
  49.                     wm.addView(floatView, params);  
  50.                     isAdded = true;  
  51.                 }  
  52.                 break;  
  53.             case OPERATION_HIDE:  
  54.                 if (isAdded) {  
  55.                     wm.removeView(floatView);  
  56.                     isAdded = false;  
  57.                 }  
  58.                 break;  
  59.             }  
  60.             copyValue = intent.getStringExtra("copyValue");  
  61.             setupCellView(floatView);  
  62.             Log.e(this.getClass().getSimpleName(), "=====copyValue :"+copyValue);  
  63.         }  
  64.     }  
  65.       
  66.     /** 
  67.      * 创建悬浮窗 
  68.      */  
  69.     private void createFloatView() {  
  70.         LayoutInflater layoutInflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);       
  71.         floatView = layoutInflater.inflate(R.layout.dict_popup_window, null);  
  72.           
  73.         wm = (WindowManager) getApplicationContext().getSystemService(Context.WINDOW_SERVICE);  
  74.         params = new WindowManager.LayoutParams();  
  75.   
  76.         // 设置window type  
  77.         params.type = WindowManager.LayoutParams.TYPE_SYSTEM_ERROR;  
  78.           
  79.         /* 
  80.          * 如果设置为params.type = WindowManager.LayoutParams.TYPE_PHONE; 那么优先级会降低一些, 
  81.          * 即拉下通知栏不可见 
  82.          */  
  83.         params.format = PixelFormat.RGBA_8888; // 设置图片格式,效果为背景透明  
  84.   
  85.         // 设置Window flag  
  86.         params.flags = WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL  
  87.                 | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;  
  88.         /* 
  89.          * 下面的flags属性的效果形同“锁定”。 悬浮窗不可触摸,不接受任何事件,同时不影响后面的事件响应。 
  90.          * wmParams.flags=LayoutParams.FLAG_NOT_TOUCH_MODAL | 
  91.          * LayoutParams.FLAG_NOT_FOCUSABLE | LayoutParams.FLAG_NOT_TOUCHABLE; 
  92.          */  
  93.   
  94.         // 设置悬浮窗的长得宽  
  95.         params.width = getResources().getDimensionPixelSize(R.dimen.float_width);  
  96.         params.height = WindowManager.LayoutParams.WRAP_CONTENT;  
  97.   
  98.         params.gravity = Gravity.LEFT | Gravity.TOP;  
  99.         params.x = 0;  
  100.         params.y = 0;  
  101.           
  102.         // 设置悬浮窗的Touch监听  
  103.         floatView.setOnTouchListener(new OnTouchListener() {  
  104.               
  105.             @Override  
  106.             public boolean onTouch(View v, MotionEvent event) {  
  107.                 x = event.getRawX();  
  108.                 y = event.getRawY();  
  109.                   
  110.                 switch(event.getAction()){  
  111.                 case MotionEvent.ACTION_DOWN:  
  112.                     startX = event.getX();  
  113.                     startY = event.getY();  
  114.                     break;  
  115.                 case MotionEvent.ACTION_MOVE:                     
  116.                     params.x = (int)( x - startX);    
  117.                     params.y = (int) (y - startY);    
  118.                     wm.updateViewLayout(floatView, params);  
  119.                     break;  
  120.                 case MotionEvent.ACTION_UP:  
  121.                     startX = startY = 0;    
  122.                     break;  
  123.                 }  
  124.                 return true;  
  125.             }  
  126.         });  
  127.           
  128.         wm.addView(floatView, params);  
  129.         isAdded = true;  
  130.     }  
  131.   
  132.     /** 
  133.      * 设置浮窗view内部子控件 
  134.      * @param rootview 
  135.      */  
  136.     private void setupCellView(View rootview) {  
  137.         ImageView closedImg = (ImageView) rootview.findViewById(R.id.float_window_closed);  
  138.         TextView titleText = (TextView) rootview.findViewById(R.id.float_window_title);  
  139.         titleText.setText(copyValue);         
  140.         closedImg.setOnClickListener(new OnClickListener() {  
  141.               
  142.             @Override  
  143.             public void onClick(View v) {  
  144.                 if (isAdded) {  
  145.                     wm.removeView(floatView);  
  146.                     isAdded = false;  
  147.                 }  
  148.             }  
  149.         });  
  150.         floatView.setOnClickListener(new OnClickListener() {  
  151.               
  152.             @Override  
  153.             public void onClick(View v) {  
  154.               
  155.             }  
  156.         });  
  157.     }  
  158.   
  159.   
  160. }  
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值