为webview添加复制文本的功能

 

需求描述:  

  • 长按WebView出现Context menu,显示"复制”菜单
  • 点击上述菜单后选择文本,复制到剪贴板
概要设计+详细设计:
  • 用OnTouchListener实现长按实现(参照android.view.View)
  • 实现WebView的Context menu(在Activity实例中实现)
  • 实现复制文本功能(兼容多个sdk)

编码:

Java代码 复制代码 收藏代码
        

public class WebViewCopy { 

  private Activity activity; 
  private WebView webview; 
  private  static boolean mIsSelectingText; 
   
  public static final String    TAG=WebViewCopy.class.getSimpleName(); 
      public WebViewCopy(final Activity activity, final WebView webView){ 
     this.webview=webView; 
     this.activity=activity; 
     this.activity.registerForContextMenu(this.webview); 
       webView.requestFocus(View.FOCUS_DOWN); 
       webView.setOnTouchListener(new OnTouchListener() { 
            
           boolean mHasPerformedLongPress; 
Runnable mPendingCheckForLongPress;
            
        
       @Override 
       public boolean onTouch(final View v, MotionEvent event) { 
        
       /*  webView.getSettings().setBuiltInZoomControls(false);
           webView.getSettings().setSupportZoom(false);*/ 
           Log.d(TAG, "event:" + event.getAction()); 
            
           switch (event.getAction()) { 
               case MotionEvent.ACTION_UP: 
                   mIsSelectingText = false; 
                    if (!v.hasFocus()) { 
                        v.requestFocus(); 
                       } 
 
                     if (!mHasPerformedLongPress) { 
                         // This is a tap, so remove the longpress check 
                         if (mPendingCheckForLongPress != null) { 
                             v.removeCallbacks(mPendingCheckForLongPress); 
                         } 
                      // v.performClick(); 
                     } 
                          
                       break; 
               case  MotionEvent.ACTION_DOWN: 
                    
                    if (!v.hasFocus()) { 
                        v.requestFocus(); 
                      } 
 
                   if( mPendingCheckForLongPress == null) { 
                        
                        
                       mPendingCheckForLongPress = new Runnable() { 
                           public void run() { 
                               //((WebView)v).performLongClick(); 
                               if(! mIsSelectingText) { 
                                   activity.openContextMenu(webview); 
                                   mHasPerformedLongPress = true; 
                                   mIsSelectingText = false; 
                               } 
                           } 
                   }; 
                        
                   } 
                    
                    
                    mHasPerformedLongPress = false; 
                    v. postDelayed(mPendingCheckForLongPress, ViewConfiguration.getLongPressTimeout()); 
                    
                       break; 
                
                case MotionEvent.ACTION_MOVE: 
                     final int x = (int) event.getX(); 
                     final int y = (int) event.getY(); 
 
                     // Be lenient about moving outside of buttons 
                     int slop = ViewConfiguration.get(v.getContext()).getScaledTouchSlop(); 
                     if ((x < 0 - slop) || (x >= v.getWidth() + slop) || 
                             (y < 0 - slop) || (y >= v.getHeight() + slop)) { 
                          
                         if (mPendingCheckForLongPress != null) { 
                            v. removeCallbacks(mPendingCheckForLongPress); 
                         } 
                     
                     } 
                       break; 
                 default: 
                     return false; 
            
           } 
            
            return false; 
            
       } 
   }); 
        
    
        
        
        
  } 
   
    public  static synchronized void  emulateShiftHeld(WebView view) 
     { 
          
            try 
            { 
                KeyEvent shiftPressEvent = new KeyEvent(0, 0, KeyEvent.ACTION_DOWN, 
                                                        KeyEvent.KEYCODE_SHIFT_LEFT, 0, 0); 
                shiftPressEvent.dispatch(view); 
            } 
            catch (Exception e) 
            { 
                Log.e(TAG, "Exception in emulateShiftHeld()", e); 
            } 
        } 
      
        public synchronized void onCreateContextMenu(ContextMenu menu, View v,   
                 ContextMenuInfo menuInfo,final int copy,String menuString) {    
                 MenuItem menuitem=menu.add(1, copy, Menu.NONE, menuString);   
                 menuitem.setOnMenuItemClickListener(new OnMenuItemClickListener() { 
                     
                    @Override 
                    public boolean onMenuItemClick(MenuItem item) { 
                        if(item.getItemId()==copy){ 
                            //emulateShiftHeld(webview); 
                            selectAndCopyText(webview); 
                        } 
                        return false; 
                    } 
                }); 
}   
        public  static synchronized void selectAndCopyText(WebView v) { 
             try { 
                  
                 mIsSelectingText = true; 
                  
                         //Method m = WebView.class.getMethod("emulateShiftHeld", Boolean.TYPE);  
                  //  m.invoke(v, false);  
                  
                if (android.os.Build.VERSION.SDK_INT <= Build.VERSION_CODES.ECLAIR) { 
                     Method m = WebView.class.getMethod("emulateShiftHeld", Boolean.TYPE);  
                       m.invoke(v, false);  
                 } 
                 else  { 
                     Method m = WebView.class.getMethod("emulateShiftHeld");  
                      m.invoke(v);  
                 } 
                  
                } catch (Exception e) { 
                    // fallback 
                    emulateShiftHeld(v); 
                }finally{ 
                    //Toast.makeText(activity, "Select text", Toast.LENGTH_SHORT).show(); 
                } 
 
        } 

public class WebViewCopy {
	private Activity activity;
	private WebView webview;
	private  static boolean mIsSelectingText;
	
	public static final String    TAG=WebViewCopy.class.getSimpleName();
        public WebViewCopy(final Activity activity, final WebView webView){
	   this.webview=webView;
	   this.activity=activity;
	   this.activity.registerForContextMenu(this.webview);
	    webView.requestFocus(View.FOCUS_DOWN);
	   	webView.setOnTouchListener(new OnTouchListener() {
	   		
	   		boolean mHasPerformedLongPress;
	   		Runnable mPendingCheckForLongPress;
	   		
		
		@Override
		public boolean onTouch(final View v, MotionEvent event) {
		
		/*	webView.getSettings().setBuiltInZoomControls(false);
			webView.getSettings().setSupportZoom(false);*/
			Log.d(TAG, "event:" + event.getAction());
			
			switch (event.getAction()) {
            	case MotionEvent.ACTION_UP:
            		mIsSelectingText = false;
            		 if (!v.hasFocus()) {
                         v.requestFocus();
                        }

            		  if (!mHasPerformedLongPress) {
                          // This is a tap, so remove the longpress check
                          if (mPendingCheckForLongPress != null) {
                              v.removeCallbacks(mPendingCheckForLongPress);
                          }
                       // v.performClick();
            		  }
                          
            			break;
            	case  MotionEvent.ACTION_DOWN:
            		
            		 if (!v.hasFocus()) {
                         v.requestFocus();
                       }

            		if( mPendingCheckForLongPress == null) {
            			
            			
            			mPendingCheckForLongPress = new Runnable() {
            				public void run() {
            					//((WebView)v).performLongClick();
            					if(! mIsSelectingText) {
	            					activity.openContextMenu(webview);
	            					mHasPerformedLongPress = true;
	            					mIsSelectingText = false;
            					}
            				}
            		};
            			
            		}
            		
            		
            		 mHasPerformedLongPress = false;
            		 v. postDelayed(mPendingCheckForLongPress, ViewConfiguration.getLongPressTimeout());
            		
            			break;
            	
            	 case MotionEvent.ACTION_MOVE:
            		  final int x = (int) event.getX();
                      final int y = (int) event.getY();

                      // Be lenient about moving outside of buttons
                      int slop = ViewConfiguration.get(v.getContext()).getScaledTouchSlop();
                      if ((x < 0 - slop) || (x >= v.getWidth() + slop) ||
                              (y < 0 - slop) || (y >= v.getHeight() + slop)) {
                    	  
                    	  if (mPendingCheckForLongPress != null) {
                             v. removeCallbacks(mPendingCheckForLongPress);
                          }
            		 
                      }
            		 	break;
            	  default:
            		  return false;
			
			}
			
			 return false;
			
		}
	});
	   	
	
	   	
	   	
	   	
   }
   
	 public  static synchronized void  emulateShiftHeld(WebView view)
	 {
		 
	        try
	        {
	            KeyEvent shiftPressEvent = new KeyEvent(0, 0, KeyEvent.ACTION_DOWN,
	                                                    KeyEvent.KEYCODE_SHIFT_LEFT, 0, 0);
	            shiftPressEvent.dispatch(view);
	        }
	        catch (Exception e)
	        {
	            Log.e(TAG, "Exception in emulateShiftHeld()", e);
	        }
	    }
	 
		public synchronized void onCreateContextMenu(ContextMenu menu, View v,  
	             ContextMenuInfo menuInfo,final int copy,String menuString) {   
	             MenuItem menuitem=menu.add(1, copy, Menu.NONE, menuString);  
	             menuitem.setOnMenuItemClickListener(new OnMenuItemClickListener() {
					
					@Override
					public boolean onMenuItemClick(MenuItem item) {
						if(item.getItemId()==copy){
							//emulateShiftHeld(webview);
							selectAndCopyText(webview);
						}
						return false;
					}
				});
}  
		public  static synchronized void selectAndCopyText(WebView v) {
		     try {
		    	 
		    	 mIsSelectingText = true;
		    	 
                         //Method m = WebView.class.getMethod("emulateShiftHeld", Boolean.TYPE); 
		          //  m.invoke(v, false); 
		    	 
		    	if (android.os.Build.VERSION.SDK_INT <= Build.VERSION_CODES.ECLAIR) {
		    		 Method m = WebView.class.getMethod("emulateShiftHeld", Boolean.TYPE); 
			           m.invoke(v, false); 
		    	 }
		    	 else  {
		    		 Method m = WebView.class.getMethod("emulateShiftHeld"); 
			    	  m.invoke(v); 
		    	 }
		         
		        } catch (Exception e) {
		            // fallback
		            emulateShiftHeld(v);
		        }finally{
		        	//Toast.makeText(activity, "Select text", Toast.LENGTH_SHORT).show();
		        }

		}
}

下面的代码在activity中写:

     1) 在onCreate中生成 WebViewCopy  实例: copy = new WebViewCopy(this, _webView);

     2) 在onCreateContextMenu中注入复制菜单public void onCreateContextMenu(ContextMenu menu, View v,

Java代码 复制代码 收藏代码
  1.     ContextMenuInfo menuInfo) {   
  2.    copy.onCreateContextMenu(menu, v, menuInfo,COPY,getString(R.string.copy)); 
  3. super.onCreateContextMenu(menu, v, menuInfo);   
			             ContextMenuInfo menuInfo) {  
		             copy.onCreateContextMenu(menu, v, menuInfo,COPY,getString(R.string.copy));
			         super.onCreateContextMenu(menu, v, menuInfo);  
		}

回顾与总结:

        OnTouchListener可能在一些时候更本不响应,如Zoom Button出现后。这得让WebView重新获取焦点,

这是WebView又一已知的Bug.  整个难点在于重新获取焦点:  webview.requestFocus();

参考: http://code.google.com/p/android/issues/detail?id=7189

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值