2011-02-26 42 views
61

Có một số phương pháp trong WebSettings liên quan đến phóng to:bật/tắt zoom trong Android WebView

  • WebSettings.setSupportZoom
  • WebSettings.setBuiltInZoomControls

tôi nhận thấy họ làm việc khác nhau trên một số thiết bị. Ví dụ, trên pinch Galaxy S của tôi để phóng to được kích hoạt theo mặc định, nhưng trên LG P500 nó bị vô hiệu hóa (Và bây giờ tôi không biết làm thế nào để kích hoạt chỉ pinch để phóng to, nhưng ẩn các nút zoom).

Trên P500 khi tôi gọi setBuiltInZoomControls(true) Tôi nhận được cả hai biến thể này hoạt động (cảm ứng đa điểm và nút).

Cách bật thu phóng đa chạm và tắt các nút thu phóng trên các thiết bị như LG P500? (Ngoài ra, tôi biết những vấn đề tương tự có trên các thiết bị HTC)

UPDATE: Đây là gần như đầy đủ mã cho các giải pháp

if (ev.getAction() == MotionEvent.ACTION_DOWN || 
      ev.getAction() == MotionEvent.ACTION_POINTER_DOWN || 
      ev.getAction() == MotionEvent.ACTION_POINTER_1_DOWN || 
      ev.getAction() == MotionEvent.ACTION_POINTER_2_DOWN || 
      ev.getAction() == MotionEvent.ACTION_POINTER_3_DOWN) { 
     if (multiTouchZoom && !buttonsZoom) { 
      if (getPointerCount(ev) > 1) { 
       getSettings().setBuiltInZoomControls(true); 
       getSettings().setSupportZoom(true); 
      } else { 
       getSettings().setBuiltInZoomControls(false); 
       getSettings().setSupportZoom(false); 
      } 
     } 
    } 

    if (!multiTouchZoom && buttonsZoom) { 
     if (getPointerCount(ev) > 1) { 
      return true; 
     } 
    } 

Mã này là trong onTouchEvent phương pháp ghi đè của tôi về WebView.

+6

Tôi có cùng một vấn đề .. multiTouchZoom và biến buttonZoom là gì? – Luciano

+1

@Luizje Tôi biết đây là cũ, nhưng trong trường hợp bất cứ ai khác tìm thấy nó: Thay đổi getPointerCount (ev) để ev.getPointerCount() và nó sẽ làm việc! –

+1

Tôi không chắc chắn nếu có ai cần điều này nữa, nhưng có một cái nhìn của tôi "hack xung quanh". Nó hoạt động trở lại Android 1.6 –

Trả lời

36

Tôi đã xem mã nguồn cho WebView và tôi kết luận rằng không có cách nào thanh lịch để thực hiện những gì bạn đang yêu cầu.

Điều tôi đã kết thúc là phân lớp WebView và ghi đè OnTouchEvent. Trong OnTouchEvent cho ACTION_DOWN, tôi kiểm tra số lượng con trỏ đang sử dụng MotionEvent.getPointerCount(). Nếu có nhiều hơn một con trỏ, tôi gọi setSupportZoom(true), nếu không, tôi gọi setSupportZoom(false). Sau đó, tôi gọi số super.OnTouchEvent().

Điều này sẽ vô hiệu hóa thu phóng khi di chuyển (do đó tắt điều khiển thu phóng) và cho phép thu phóng khi người dùng sắp thu nhỏ thu phóng. Không phải là một cách tốt đẹp để làm điều đó, nhưng nó đã làm việc tốt cho tôi cho đến nay.

Lưu ý rằng getPointerCount() đã được giới thiệu trong 2.1 nên bạn sẽ phải thực hiện thêm một số thứ nếu bạn hỗ trợ 1.6.

+1

Cảm ơn giải pháp đó. Nó hoạt động gần như theo cách tôi muốn. Tôi sẽ gửi bản tóm tắt mã trong câu hỏi –

+8

Tôi đã nói tôi yêu bạn chưa, gngr44? – Cristian

+0

Tuyệt vời !! Cảm ơn rất nhiều :) – nithinreddy

1

Giải pháp bạn đã đăng có vẻ hoạt động khi dừng điều khiển thu phóng xuất hiện khi người dùng kéo, tuy nhiên có những trường hợp người dùng sẽ thu phóng và điều khiển thu phóng sẽ xuất hiện. Tôi đã nhận thấy rằng có 2 cách mà các webview sẽ chấp nhận nhúm zoom, và chỉ một trong số họ gây ra các điều khiển zoom để xuất hiện mặc dù mã của bạn:

tài Pinch phóng và điều khiển xuất hiện:

ACTION_DOWN 
getSettings().setBuiltInZoomControls(false); getSettings().setSupportZoom(false); 
ACTION_POINTER_2_DOWN 
getSettings().setBuiltInZoomControls(true); getSettings().setSupportZoom(true); 
ACTION_MOVE (Repeat several times, as the user moves their fingers) 
ACTION_POINTER_2_UP 
ACTION_UP 

Zoom và điều khiển Pinch của người dùng không xuất hiện:

ACTION_DOWN 
getSettings().setBuiltInZoomControls(false); getSettings().setSupportZoom(false); 
ACTION_POINTER_2_DOWN 
getSettings().setBuiltInZoomControls(true); getSettings().setSupportZoom(true); 
ACTION_MOVE (Repeat several times, as the user moves their fingers) 
ACTION_POINTER_1_UP 
ACTION_POINTER_UP 
ACTION_UP 

Bạn có thể làm sáng tỏ thêm giải pháp của mình không?

106

Mở API> = 11, bạn có thể sử dụng:

wv.getSettings().setBuiltInZoomControls(true); 
wv.getSettings().setDisplayZoomControls(false); 

Theo SDK:

public void setDisplayZoomControls (boolean enabled) 

Since: API Level 11

Sets whether the on screen zoom buttons are used. A combination of built in zoom controls enabled and on screen zoom controls disabled allows for pinch to zoom to work without the on screen controls

+9

Quá xấu 60% + người dùng vẫn đang sử dụng API trước 11 ... và tôi đang nói điều này một năm sau khi bạn đăng! Các con số trông như thế nào khi bạn đăng đề xuất? – ArtOfWarfare

+0

Tôi đã sử dụng tính năng này với [câu trả lời này] (http://stackoverflow.com/a/13543216/536986) để mặc định chế độ xem của tôi được thu nhỏ và có thể chụm để thu phóng. Tôi vừa rời khỏi phần hiển thị để làm việc với pre-API 11 – Cameron

+0

Câu trả lời hay. Ngoài ra hãy chắc chắn rằng một yếu tố kiểm soát là "sử dụng khả năng mở rộng" trong meta

29

Chúng tôi đã có cùng một vấn đề khi làm việc trên một ứng dụng Android cho một khách hàng và tôi đã cố gắng "hack" xung quanh hạn chế này.

Tôi đã xem mã nguồn Android cho lớp WebView và phát hiện một updateZoomButtonsEnabled()-method đang hoạt động với ZoomButtonsController-object để bật và tắt các điều khiển thu phóng tùy thuộc vào quy mô hiện tại của trình duyệt.

Tôi đã tìm kiếm phương thức trả lại số ZoomButtonsController -instance và tìm thấy số getZoomButtonsController()-method, trả về ví dụ này.

Mặc dù phương thức được khai báo là public, nhưng nó không được ghi trong tài liệu WebView và Eclipse cũng không thể tìm thấy nó. Vì vậy, tôi đã thử một số phản ánh về điều đó và tạo riêng lớp học WebView của riêng mình để ghi đè lên phương pháp onTouchEvent(), kích hoạt các điều khiển.

public class NoZoomControllWebView extends WebView { 

    private ZoomButtonsController zoom_controll = null; 

    public NoZoomControllWebView(Context context) { 
     super(context); 
     disableControls(); 
    } 

    public NoZoomControllWebView(Context context, AttributeSet attrs, int defStyle) { 
     super(context, attrs, defStyle); 
     disableControls(); 
    } 

    public NoZoomControllWebView(Context context, AttributeSet attrs) { 
     super(context, attrs); 
     disableControls(); 
    } 

    /** 
    * Disable the controls 
    */ 
    private void disableControls(){ 
     if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.HONEYCOMB) { 
      // Use the API 11+ calls to disable the controls 
      this.getSettings().setBuiltInZoomControls(true); 
      this.getSettings().setDisplayZoomControls(false); 
     } else { 
      // Use the reflection magic to make it work on earlier APIs 
      getControlls(); 
     } 
    } 

    /** 
    * This is where the magic happens :D 
    */ 
    private void getControlls() { 
     try { 
      Class webview = Class.forName("android.webkit.WebView"); 
      Method method = webview.getMethod("getZoomButtonsController"); 
      zoom_controll = (ZoomButtonsController) method.invoke(this, null); 
     } catch (Exception e) { 
      e.printStackTrace(); 
     } 
    } 

    @Override 
    public boolean onTouchEvent(MotionEvent ev) { 
     super.onTouchEvent(ev); 
     if (zoom_controll != null){ 
      // Hide the controlls AFTER they where made visible by the default implementation. 
      zoom_controll.setVisible(false); 
     } 
     return true; 
    } 
} 

Bạn có thể muốn loại bỏ các hàm tạo không cần thiết và phản ứng có thể trên các ngoại lệ.

Mặc dù điều này có vẻ hacky và không đáng tin cậy, nó làm việc trở lại API Level 4 (Android 1.6).


Như @jayellos chỉ ra trong các ý kiến, các tin getZoomButtonsController() -method là không còn tồn tại trên Android 4.0.4 và sau đó.

Tuy nhiên, nó không cần. Sử dụng conditional execution, chúng ta có thể kiểm tra xem chúng ta đang ở trên một thiết bị với API Cấp 11 + và sử dụng các chức năng tiếp xúc (xem @Yuttadhammo câu trả lời) để ẩn các điều khiển.

tôi cập nhật mã ví dụ trên để làm chính xác điều đó.

+0

@Lukas, nó sẽ không hoạt động trên Android 4.0.4. Nó trả về NoSuchMethodException: getZoomButtonsController. – jayellos

+1

@jayellos Trên Android 4 bạn có thể sử dụng (http://developer.android.com/reference/android/webkit/WebSettings.html#setDisplayZoomControls%28boolean%29) phương pháp [ ' 'WebSettings.setDisplayZoomControls (boolean)] đó là có sẵn từ cấp API 11. –

+0

@LukasKnuth cảm ơn sự giúp đỡ của bạn. Bây giờ nó hoạt động. Tôi thay đổi cấp Api mục tiêu thành 11+. Như đã nói ở thực thi có điều kiện. Trước khi Api mục tiêu của tôi là 10 nên tôi không thể sử dụng hàm .setDisplayZoomControls (boolean). Một lần nữa, cảm ơn bạn. – jayellos

7

Lukas Knuth có giải pháp tốt, nhưng trên 4.0.4 android trên Samsung Galaxy SII tôi vẫn tìm kiếm điều khiển zoom. Và tôi giải quyết nó qua

if (zoom_controll!=null && zoom_controll.getZoomControls()!=null) 
{ 
    // Hide the controlls AFTER they where made visible by the default implementation. 
    zoom_controll.getZoomControls().setVisibility(View.GONE); 
} 

thay vì

if (zoom_controll != null){ 
    // Hide the controlls AFTER they where made visible by the default implementation. 
    zoom_controll.setVisible(false); 
} 
+0

Tôi biết câu trả lời này đã được vài tháng, nhưng tôi chỉ muốn Câu trả lời này kết hợp với Lukas Knuth là hoàn hảo – anthonycr

10

Ive modifiet giải pháp Lukas Knuth một chút:

1) Không cần phải phân lớp webview,

2) mã sẽ sụp đổ trong xác minh bytecode trên một số thiết bị Android 1.6 nếu bạn không đưa phương pháp nonexistant trong các lớp riêng biệt

01.

3) Điều khiển thu phóng sẽ vẫn xuất hiện nếu người dùng cuộn lên/xuống một trang.Tôi chỉ cần đặt container điều khiển zoom để tầm nhìn GONE

wv.getSettings().setSupportZoom(true); 
    wv.getSettings().setBuiltInZoomControls(true); 
    if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.HONEYCOMB) { 
    // Use the API 11+ calls to disable the controls 
    // Use a seperate class to obtain 1.6 compatibility 
    new Runnable() { 
     public void run() { 
     wv.getSettings().setDisplayZoomControls(false); 
     } 
    }.run(); 
    } else { 
    final ZoomButtonsController zoom_controll = 
     (ZoomButtonsController) wv.getClass().getMethod("getZoomButtonsController").invoke(wv, null); 
    zoom_controll.getContainer().setVisibility(View.GONE); 
    } 
+0

Giải pháp hoàn hảo Chỉ điều tôi muốn thay đổi là gọi (webview, (Object []) null)) vì vậy bạn không nhận được cảnh báo trong Eclipse. – twig

+0

Trông giống như một giải pháp tốt. Tôi không thể biên dịch vì lỗi này: Gọi đòi hỏi mức API 11 (hiện tại tối thiểu là 8): android.webkit.WebSettings # setDisplayZoomControls – ropo

+0

Nhấn Ctrl-1 cho @SuppressLint – ropo

1

Cải thiện Lukas Knuth phiên bản:

public class TweakedWebView extends WebView { 

    private ZoomButtonsController zoomButtons; 

    public TweakedWebView(Context context) { 
     super(context); 
     init(); 
    } 

    public TweakedWebView(Context context, AttributeSet attrs) { 
     super(context, attrs); 
     init(); 
    } 

    public TweakedWebView(Context context, AttributeSet attrs, int defStyle) { 
     super(context, attrs, defStyle); 
     init(); 
    } 

    private void init() { 
     getSettings().setBuiltInZoomControls(true); 
     if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) { 
      getSettings().setDisplayZoomControls(false); 
     } else { 
      try { 
       Method method = getClass() 
         .getMethod("getZoomButtonsController"); 
       zoomButtons = (ZoomButtonsController) method.invoke(this); 
      } catch (Exception e) { 
       // pass 
      } 
     } 
    } 

    @Override 
    public boolean onTouchEvent(MotionEvent ev) { 
     boolean result = super.onTouchEvent(ev); 
     if (zoomButtons != null) { 
      zoomButtons.setVisible(false); 
      zoomButtons.getZoomControls().setVisibility(View.GONE); 
     } 
     return result; 
    } 

} 
0

hey there cho bất cứ ai có thể tìm kiếm giải pháp như thế này .. tôi đã có vấn đề với mở rộng quy mô bên trong WebView do đó, cách tốt nhất để làm là trong java.class nơi bạn đặt tất cả cho WebView đặt hai dòng mã này: (webViewSearch là tên của WebView của tôi -> webViewSearch = (WebView) findViewById (R.id.id_webview_search);)

// force WebView to show content not zoomed--------------------------------------------------------- 
    webViewSearch.getSettings().setLoadWithOverviewMode(true); 
    webViewSearch.getSettings().setUseWideViewPort(true); 
+0

có phải là chế độ máy tính để bàn không? –

+0

hm, vì webView là chế độ xem hiển thị trang web và hai định dạng đó là: setLoadWithOverviewMode (tổng quan boolean) Đặt xem WebView có tải trang ở chế độ tổng quan hay không, thu nhỏ nội dung vừa với màn hình theo chiều rộng , và setUseWideViewPort (sử dụng boolean) Đặt xem WebView có bật hỗ trợ cho thẻ meta HTML "viewport" hoặc nên sử dụng chế độ xem rộng không. Bạn có thể nói điều đó giống như chế độ destkop ^^ – Perhpethua

+0

Tôi chỉ tự hỏi làm cách nào mà trình duyệt web của bên thứ ba chuyển sang chế độ "máy tính để bàn". Tôi không nghĩ họ sử dụng cái này. Tôi nghĩ rằng họ thay đổi tác nhân người dùng hoặc một cái gì đó. –