android 关于WebView点击图片展示大图

来源:互联网 发布:android彩票源码 编辑:程序博客网 时间:2024/04/30 03:29

最近因为项目的需要 在加载webview的时候如果有图片展示点击能够查看大图,刚开始百思不得其解,后来经过多方的努力得以实现。
这一行代码是为了重写js交互
webView.setWebViewClient(new MyWebViewClient(context, webView, layout_loding));
能够实现这样的功能 无外乎有两步 第一能够识别JS的语言

例如上面这段JS代码。
至于这个首先你的重写WebViewClient 这个类。代码如下
import android.content.Context;
import android.graphics.Bitmap;
import android.util.Log;
import android.view.View;
import android.webkit.CookieManager;
import android.webkit.WebSettings;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.widget.ProgressBar;

import java.net.URLDecoder;
import java.util.HashSet;
import java.util.Set;

import cn.jpush.android.api.JPushInterface;
import cn.jpush.android.api.TagAliasCallback;

/**
* Created by xiaomo on
*/
public class MyWebViewClient extends WebViewClient {

private static final String TAG = "MyWebViewClient";private ProgressBar layout_loding;private Context mContext;private WebView mwebView;public MyWebViewClient( Context context,WebView webView,ProgressBar layout_loding) {    this.layout_loding = layout_loding;    this.mContext = context;    this.mwebView =webView;}@Overridepublic boolean shouldOverrideUrlLoading(WebView view, String url) {    view.loadUrl(url);    return true;}@Overridepublic void onPageStarted(WebView view, String url, Bitmap favicon) {    // TODO Auto-generated method stub    super.onPageStarted(view, url, favicon);}@Overridepublic void onPageFinished(WebView view, String url) {    super.onPageFinished(view, url);    addImageClickListner();    layout_loding.setVisibility(View.GONE);}@Overridepublic void onReceivedError(WebView view, int errorCode, String description, String failingUrl) {    super.onReceivedError(view, errorCode, description, failingUrl);    layout_loding.setVisibility(View.GONE);}private void addImageClickListner() {    mwebView.loadUrl("javascript:(function(){" +            "var objs = document.getElementsByClassName(\"upload-img\"); " +            "for(var i=0;i<objs.length;i++)  " +            "{"            + "    objs[i].onclick=function()  " +            "    {  "            + "        window.imagelistner.openImage(this.src);  " +            "    }  " +            "}" +            "})()");}

}
最要的莫过于就是这里写图片描述

这个得和js端协调一下 ,我用之前的方法 所有图片都能点击放大 ,因为我的这个项目里有获取图片验证码 ,尴尬的一幕发生了,本来想点击更换验证码的 居然放大了。后来我找来了写JS的人 他帮忙修改了一下得以解决。

这一步写完了话 完成了一半,紧接着是第二步

webView.addJavascriptInterface(new JavascriptInterface(context), “imagelistner”);
这是添加回调方法,需要重写。主要的目的是 js返回的图片地址链接和保存图片地址,接着往下看这段代码:
/**
* Created by xiaomo
*/

public class JavascriptInterface {

private Context context;public JavascriptInterface(Context context) {    this.context = context;}@android.webkit.JavascriptInterfacepublic void openImage(String img) {    System.out.println(img);    Intent intent = new Intent();    intent.putExtra("image", img);    intent.setClass(context, ShowImgActivity.class);    context.startActivity(intent);    System.out.println(img);}

}
上面这个intent 为了传递图片地址,你也可以用其他的方式保存起来然后调用。
实现了这些 还有最重要的 ,怎样才能实现像微信一样能够点击放大图片并且能都支持手指缩放咧!这里为网上找了一段实现的类 如下:

/*
* Copyright 2012 Laurence Dawson
*
* Licensed under the Apache License, Version 2.0 (the “License”);
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an “AS IS” BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

/*
* This class is based upon the file ImageViewTouchBase.java which can be found at:
* https://dl-ssl.google.com/dl/googlesource/git-repo/repo
*
* Copyright (C) 2009 The Android Open Source Project
*/

import android.annotation.SuppressLint;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.os.Build;
import android.os.SystemClock;
import android.util.AttributeSet;
import android.view.GestureDetector;
import android.view.MotionEvent;
import android.view.ScaleGestureDetector;
import android.view.View;
import android.view.animation.Animation;
import android.view.animation.TranslateAnimation;

@SuppressLint(“NewApi”)
public class ZoomableImageView extends View {

// Staticsstatic final float sPanRate = 7;static final float sScaleRate = 1.25F;static final int sPaintDelay = 250;static final int sAnimationDelay = 500;// This is the base transformation which is used to show the image// initially.  The current computation for this shows the image in// it's entirety, letterboxing as needed.  One could chose to// show the image as cropped instead.  //// This matrix is recomputed when we go from the thumbnail image to// the full size image.private Matrix mBaseMatrix = new Matrix();// This is the supplementary transformation which reflects what // the user has done in terms of zooming and panning.//// This matrix remains the same when we go from the thumbnail image// to the full size image.private Matrix mSuppMatrix = new Matrix();// This is the final matrix which is computed as the concatentation// of the base matrix and the supplementary matrix.private Matrix mDisplayMatrix = new Matrix();// A replacement ImageView matrixprivate Matrix mMatrix = new Matrix();// Used to filter the bitmaps when hardware acceleration is not enabledprivate Paint mPaint;// Temporary buffer used for getting the values out of a matrix.private float[] mMatrixValues = new float[9];// The current bitmap being displayed.private Bitmap mBitmap;// Dimensions for the viewprivate int mThisWidth = -1, mThisHeight = -1;// The max zoom for the view, determined programaticallyprivate float mMaxZoom;// If not null, calls setImageBitmap when onLayout is triggeredprivate Runnable mOnLayoutRunnable = null;// Stacked to the internal queue to invalidate the viewprivate Runnable mRefresh = null;// Stacked to the internal queue to scroll the viewprivate Runnable mFling = null;// The time of the last draw operationprivate double mLastDraw = 0;// Scale and gesture listeners for the viewprivate ScaleGestureDetector mScaleDetector;private GestureDetector mGestureDetector;// Single tap listenerprivate OnImageTouchedListener mImageTouchedListener;private OnDownActionListener mDown = null;// Programatic entry pointpublic ZoomableImageView(Context context) {    super(context);    init( context );}// Set the single tap listenerpublic void setOnImageTouchedListener( OnImageTouchedListener listener ){    this.mImageTouchedListener = listener;}// 为每个接口设置监听器public void setOnDownActionListener(OnDownActionListener down) {    mDown = down;}// 定义三个接口public interface OnDownActionListener {    public void OnDown(int x, int y);}// XML entry pointpublic ZoomableImageView(Context context, AttributeSet attrs) {    super(context, attrs);    init( context );}// Setup the viewprivate void init( Context context) {    mPaint = new Paint();    mPaint.setDither(true);    mPaint.setFilterBitmap(true);    mPaint.setAntiAlias(true);    // Setup the refresh runnable    mRefresh = new Runnable() {        @Override        public void run() {            postInvalidate();        }    };    // Setup the gesture and scale listeners    mScaleDetector = new ScaleGestureDetector( context, new ScaleListener() );    mGestureDetector = new GestureDetector(context, new MyGestureListener());    // Force hardware acceleration    if( Build.VERSION.SDK_INT >=  Build.VERSION_CODES.HONEYCOMB )        setLayerType(View.LAYER_TYPE_HARDWARE, null);}// Get the bitmap for the viewpublic Bitmap getImageBitmap(){    return mBitmap;}// Free the bitmaps and matricespublic void clear(){    if(mBitmap!=null)        mBitmap = null;}// When the layout is calculated, set the @Overrideprotected void onLayout(boolean changed, int left, int top, int right, int bottom) {    super.onLayout(changed, left, top, right, bottom);    mThisWidth = right - left;    mThisHeight = bottom - top;    Runnable r = mOnLayoutRunnable;    if (r != null) {        mOnLayoutRunnable = null;        r.run();    }    if (mBitmap != null) {        setBaseMatrix(mBitmap, mBaseMatrix);        setImageMatrix(getImageViewMatrix());    }}// Translate a given point through a given matrix.static private void translatePoint(Matrix matrix, float [] xy) {    matrix.mapPoints(xy);}// Identical to the setImageMatrix method in ImageViewpublic void setImageMatrix(Matrix m){    if (m != null && m.isIdentity()) {        m = null;    }    // don't invalidate unless we're actually changing our matrix    if (m == null && !this.mMatrix.isIdentity() || m != null && !this.mMatrix.equals(m)) {        this.mMatrix.set(m);        invalidate();    }}// Sets the bitmap for the image and resets the basepublic void setImageBitmap(final Bitmap bitmap) {    final int viewWidth = getWidth();    if( Build.VERSION.SDK_INT >=  Build.VERSION_CODES.HONEYCOMB && bitmap!=null && bitmap.getHeight()>1800 )        setLayerType(View.LAYER_TYPE_SOFTWARE, null);    if (viewWidth <= 0)  {        mOnLayoutRunnable = new Runnable() {            public void run() {                setImageBitmap(bitmap);            }        };        return;    }    if (bitmap != null) {        setBaseMatrix(bitmap, mBaseMatrix);        this.mBitmap = bitmap;    } else {        mBaseMatrix.reset();        this.mBitmap = bitmap;    }    mSuppMatrix.reset();    setImageMatrix(getImageViewMatrix());    mMaxZoom = maxZoom();    // Set the image to fit the screen    zoomTo(zoomDefault());}// Unchanged from ImageViewTouchBase// Center as much as possible in one or both axis.  Centering is// defined as follows:  if the image is scaled down below the // view's dimensions then center it (literally).  If the image// is scaled larger than the view and is translated out of view// then translate it back into view (i.e. eliminate black bars).protected void center(boolean vertical, boolean horizontal, boolean animate) {    if (mBitmap == null)        return;    Matrix m = getImageViewMatrix();    float [] topLeft  = new float[] { 0, 0 };    float [] botRight = new float[] { mBitmap.getWidth(), mBitmap.getHeight() };    translatePoint(m, topLeft);    translatePoint(m, botRight);    float height = botRight[1] - topLeft[1];    float width  = botRight[0] - topLeft[0];    float deltaX = 0, deltaY = 0;    if (vertical) {        int viewHeight = getHeight();        if (height < viewHeight) {            deltaY = (viewHeight - height)/2 - topLeft[1];        } else if (topLeft[1] > 0) {            deltaY = -topLeft[1];        } else if (botRight[1] < viewHeight) {            deltaY = getHeight() - botRight[1];        }    }    if (horizontal) {        int viewWidth = getWidth();        if (width < viewWidth) {            deltaX = (viewWidth - width)/2 - topLeft[0];        } else if (topLeft[0] > 0) {            deltaX = -topLeft[0];        } else if (botRight[0] < viewWidth) {            deltaX = viewWidth - botRight[0];        }    }    postTranslate(deltaX, deltaY);    if (animate) {        Animation a = new TranslateAnimation(-deltaX, 0, -deltaY, 0);        a.setStartTime(SystemClock.elapsedRealtime());        a.setDuration(250);        setAnimation(a);    }    setImageMatrix(getImageViewMatrix());}// Unchanged from ImageViewTouchBaseprotected float getValue(Matrix matrix, int whichValue) {    matrix.getValues(mMatrixValues);    return mMatrixValues[whichValue];}// Get the scale factor out of the matrix.protected float getScale(Matrix matrix) {    // If the bitmap is set return the scale    if(mBitmap!=null)        return getValue(matrix, Matrix.MSCALE_X);    // Otherwise return the default value of 1    else        return 1f;}// Returns the current scale of the view public float getScale() {    return getScale(mSuppMatrix);}// Setup the base matrix so that the image is centered and scaled properly.private void setBaseMatrix(Bitmap bitmap, Matrix matrix) {    float viewWidth = getWidth();    float viewHeight = getHeight();    matrix.reset();    float widthScale = Math.min(viewWidth / (float)bitmap.getWidth(), 1.0f);    float heightScale = Math.min(viewHeight / (float)bitmap.getHeight(), 1.0f);    float scale;    if (widthScale > heightScale) {        scale = heightScale;    } else {        scale = widthScale;    }    matrix.setScale(scale, scale);    matrix.postTranslate(            (viewWidth  - ((float)bitmap.getWidth()  * scale))/2F,             (viewHeight - ((float)bitmap.getHeight() * scale))/2F);}// Combine the base matrix and the supp matrix to make the final matrix.protected Matrix getImageViewMatrix() {    mDisplayMatrix.set(mBaseMatrix);    mDisplayMatrix.postConcat(mSuppMatrix);    return mDisplayMatrix;}// Sets the maximum zoom, which is a scale relative to the base matrix. It is calculated to show// the image at 400% zoom regardless of screen or image orientation. If in the future we decode// the full 3 megapixel image, rather than the current 1024x768, this should be changed down to// 200%.protected float maxZoom() {    if (mBitmap == null)        return 1F;    float fw = (float) mBitmap.getWidth()  / (float)mThisWidth;    float fh = (float) mBitmap.getHeight() / (float)mThisHeight;    float max = Math.max(fw, fh) * 16;    return max;}// Tries to make best use of the space by zooming the picturepublic float zoomDefault() {    if (mBitmap == null)        return 1F;    float fw = (float)mThisWidth/(float)mBitmap.getWidth();    float fh = (float)mThisHeight/(float)mBitmap.getHeight();    return Math.max(Math.min(fw, fh),1);}// Unchanged from ImageViewTouchBaseprotected void zoomTo(float scale, float centerX, float centerY) {    if (scale > mMaxZoom) {        scale = mMaxZoom;    }    float oldScale = getScale();    float deltaScale = scale / oldScale;    mSuppMatrix.postScale(deltaScale, deltaScale, centerX, centerY);    setImageMatrix(getImageViewMatrix());    center(true, true, false);}// Unchanged from ImageViewTouchBaseprotected void zoomTo(final float scale, final float centerX, final float centerY, final float durationMs) {    final float incrementPerMs = (scale - getScale()) / durationMs;    final float oldScale = getScale();    final long startTime = System.currentTimeMillis();    // Setup the zoom runnable    post(new Runnable() {        public void run() {            long now = System.currentTimeMillis();            float currentMs = Math.min(durationMs, (float)(now - startTime));            float target = oldScale + (incrementPerMs * currentMs);            zoomTo(target, centerX, centerY);            if (currentMs < durationMs) {                post(this);            }        }    });}// Unchanged from ImageViewTouchBasepublic void zoomTo(float scale) {    float width = getWidth();    float height = getHeight();    zoomTo(scale, width/2F, height/2F);}// Unchanged from ImageViewTouchBaseprotected void zoomIn() {    zoomIn(sScaleRate);}// Unchanged from ImageViewTouchBaseprotected void zoomOut() {    zoomOut(sScaleRate);}// Unchanged from ImageViewTouchBaseprotected void zoomIn(float rate) {    if (getScale() >= mMaxZoom) {        return;     // Don't let the user zoom into the molecular level.    }    if (mBitmap == null) {        return;    }    float width = getWidth();    float height = getHeight();    mSuppMatrix.postScale(rate, rate, width/2F, height/2F);    setImageMatrix(getImageViewMatrix());}// Unchanged from ImageViewTouchBaseprotected void zoomOut(float rate) {    if (mBitmap == null) {        return;    }    float width = getWidth();    float height = getHeight();    Matrix tmp = new Matrix(mSuppMatrix);    tmp.postScale(1F/sScaleRate, 1F/sScaleRate, width/2F, height/2F);    if (getScale(tmp) < 1F) {        mSuppMatrix.setScale(1F, 1F, width/2F, height/2F);    } else {        mSuppMatrix.postScale(1F/rate, 1F/rate, width/2F, height/2F);    }    setImageMatrix(getImageViewMatrix());    center(true, true, false);}// Unchanged from ImageViewTouchBaseprotected void postTranslate(float dx, float dy) {    mSuppMatrix.postTranslate(dx, dy);}// Fling a view by a distance over timeprotected void scrollBy( float distanceX, float distanceY, final float durationMs ){    final float dx = distanceX;    final float dy = distanceY;    final long startTime = System.currentTimeMillis();    mFling = new Runnable() {        float old_x = 0;        float old_y = 0;        public void run()        {            long now = System.currentTimeMillis();            float currentMs = Math.min( durationMs, now - startTime );            float x = easeOut( currentMs, 0, dx, durationMs );            float y = easeOut( currentMs, 0, dy, durationMs );            postTranslate( ( x - old_x ), ( y - old_y ) );            center(true, true, false);            old_x = x;            old_y = y;            if ( currentMs < durationMs ) {                post( this );            }        }    };    post( mFling );}// Gradually slows down a fling velocityprivate float easeOut( float time, float start, float end, float duration){    return end * ( ( time = time / duration - 1 ) * time * time + 1 ) + start;}// Custom draw operation to draw the bitmap using mMatrix@Overrideprotected void onDraw(Canvas canvas) {    // Check if the bitmap was ever set    if(mBitmap!=null && !mBitmap.isRecycled() ){        // If the current version is above Gingerbread and the layer type is         // hardware accelerated, the paint is no longer needed        if( Build.VERSION.SDK_INT >=  Build.VERSION_CODES.HONEYCOMB                 && getLayerType() == View.LAYER_TYPE_HARDWARE ){            canvas.drawBitmap(mBitmap, mMatrix, null);        }else{            // Check if the time between draws has been met and draw the bitmap            if( (System.currentTimeMillis()-mLastDraw) > sPaintDelay ){                canvas.drawBitmap(mBitmap, mMatrix, mPaint);                mLastDraw = System.currentTimeMillis();            }            // Otherwise draw the bitmap without the paint and resubmit a new request            else{                canvas.drawBitmap(mBitmap, mMatrix, null);                removeCallbacks(mRefresh);                postDelayed(mRefresh, sPaintDelay);            }        }    }}// Adjusts the zoom of the viewclass ScaleListener extends ScaleGestureDetector.SimpleOnScaleGestureListener {    @Override    public boolean onScale( ScaleGestureDetector detector )    {           // Check if the detector is in progress in order to proceed        if(detector!=null && detector.isInProgress() ){            try{                // Grab the scale                float targetScale = getScale() * detector.getScaleFactor();                // Correct for the min scale                targetScale = Math.min( maxZoom(), Math.max( targetScale, 1.0f) );                // Zoom and invalidate the view                zoomTo( targetScale, detector.getFocusX(), detector.getFocusY() );                invalidate();                return true;            }catch(IllegalArgumentException e){                e.printStackTrace();            }        }        return false;    }}// Handles taps and scrolls of the viewprivate class MyGestureListener extendsGestureDetector.SimpleOnGestureListener {    @Override    public boolean onSingleTapConfirmed(MotionEvent e) {        if(mImageTouchedListener!=null){            mImageTouchedListener.onImageTouched();            return false;        }        return super.onSingleTapConfirmed(e);    }    @Override    public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {        // Skip if there are multiple points of contact        if ( (e1!=null&&e1.getPointerCount() > 1) || (e2!=null&&e2.getPointerCount() > 1) || (mScaleDetector!=null && mScaleDetector.isInProgress()) )             return false;        // Scroll the bitmap        if ( getScale() > zoomDefault() ) {            removeCallbacks(mFling);            postTranslate(-distanceX, -distanceY);            center(true, true, false);        }        // Default case        return true;    }    @Override    public boolean onDoubleTap(MotionEvent e) {        // If the zoom is over 1x, reset to 1x        if ( getScale() > zoomDefault() ){            zoomTo(zoomDefault());        }        // If the zoom is default, zoom into 2x        else             zoomTo(zoomDefault()*3, e.getX(), e.getY(),200);        // Always true as double tap was performed        return true;    }    @Override    public boolean onFling( MotionEvent e1, MotionEvent e2, float velocityX, float velocityY )    {        if ( (e1!=null&&e1.getPointerCount() > 1) || (e2!=null&&e2.getPointerCount() > 1) ) return false;        if ( mScaleDetector.isInProgress() ) return false;        try{            float diffX = e2.getX() - e1.getX();            float diffY = e2.getY() - e1.getY();            if ( Math.abs( velocityX ) > 800 || Math.abs( velocityY ) > 800 ) {                scrollBy( diffX / 2, diffY / 2, 300 );                invalidate();            }        }catch(NullPointerException  e){        }        return super.onFling( e1, e2, velocityX, velocityY );    }}@Overridepublic void setOnClickListener(OnClickListener l) {    super.setOnClickListener(l);}@Overridepublic boolean onTouchEvent(MotionEvent event) {    // If the bitmap was set, check the scale and gesture detectors    if(mBitmap!=null){        // Check the scale detector        mScaleDetector.onTouchEvent( event );        // Check the gesture detector        if(!mScaleDetector.isInProgress())            mGestureDetector.onTouchEvent( event );    }

// int x, y;
// if (event.getAction() == MotionEvent.ACTION_DOWN) {
// x = (int) event.getX();
// y = (int) event.getY();
// if (mDown != null) {
// mDown.OnDown(x, y);
// }
// }
// Default case
return true;
}
}
本来想找第三的框架来处理这样问题,但是没找到,现在最新最热的加载图片的框架 fresco还有 glide都不支持可以手动缩放图片的功能!如果有更好的欢迎下方留言!我们一起共同进步!表示谢谢!如果有技术问题欢迎 加入我的QQ群 285526158.

喜欢的可以关注微信公众号,哪里每天都会推荐一篇开源项目Git项目地址在里欢迎订阅

这里写图片描述

0 0
原创粉丝点击