当前位置: 移动技术网 > IT编程>移动开发>Android > Android进阶篇-自定义图片伸缩控件具体实例

Android进阶篇-自定义图片伸缩控件具体实例

2019年07月24日  | 移动技术网IT编程  | 我要评论

黄长健,旬邑许东海,离婚律师下载

zoomimageview.java:

复制代码 代码如下:

/**
 * @author gongchaobin
 *
 *  自定义可伸缩的imageview
 */
public class zoomimageview extends view{
    /** 画笔类  **/
    private paint mpaint;

    private runnable mrefresh = null;
    /** 缩放手势监听类  **/
    private scalegesturedetector mscaledetector;
    /** 手势识别类  **/
    private gesturedetector mgesturedetector;
    /** 当前被渲染的bitmap **/
    private bitmap mbitmap;

    private int mthiswidth = -1, mthisheight = -1;

    private runnable monlayoutrunnable = null;

    private matrix mbasematrix = new matrix();
    private matrix mdisplaymatrix = new matrix();
    private matrix msuppmatrix = new matrix();
    private matrix mmatrix = new matrix();

    /** 最大的拉伸比例   **/
    private float mmaxzoom;

    private float[] mmatrixvalues = new float[9];
    private runnable mfling = null;

    private double mlastdraw = 0;
    static final int spaintdelay = 250;

    public zoomimageview(context context, attributeset attrs, int defstyle) {
        super(context, attrs, defstyle);
        // todo auto-generated constructor stub
        init();
    }

    public zoomimageview(context context, attributeset attrs) {
        super(context, attrs);
        // todo auto-generated constructor stub
        init();
    }

    public zoomimageview(context context) {
        super(context);
        // todo auto-generated constructor stub
        init();
    }

    private void init() {
        mpaint = new paint();
        // 图像抖动处理
        mpaint.setdither(true);
        // 过滤优化操作  加快显示
        mpaint.setfilterbitmap(true);
        // 去掉锯齿
        mpaint.setantialias(true);

        /** 刷新线程  **/
        mrefresh = new runnable() {
            @override
            public void run() {
                postinvalidate();
            }
        };

        mscaledetector = new scalegesturedetector(getcontext(),new scalelistener());
        mgesturedetector = new gesturedetector(getcontext(),new mygesturelistener());

        // 判断是否是新的api  开启硬件加速
        if(build.version.sdk_int >=  build.version_codes.honeycomb) {
            setlayertype(view.layer_type_hardware, null);
        }
    }

    public bitmap getimagebitmap() {
        return mbitmap;
    }

    /** 回收bitmap **/
    public void clear() {
        if(mbitmap != null && !mbitmap.isrecycled()) {
            mbitmap.recycle();
            mbitmap = null;
        }
    }

    @override
    protected void onlayout(boolean changed, int left, int top, int right,
            int bottom) {
        // todo auto-generated method stub
        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());
        }
    }

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

    protected matrix getimageviewmatrix() {
        mdisplaymatrix.set(mbasematrix);
        mdisplaymatrix.postconcat(msuppmatrix);
        return mdisplaymatrix;
    }

    public void setimagematrix(matrix m){
        /** matrix是否为空并是否定义   **/
        if (m != null && m.isidentity()) {
            m = null;
        }

        if (m == null && !this.mmatrix.isidentity() || m != null && !this.mmatrix.equals(m)) {
            this.mmatrix.set(m);
            invalidate();
        }
    }

    static private void translatepoint(matrix matrix, float [] xy) {
        matrix.mappoints(xy);
    }

    /**
     * 设置bitmap
     *
     * @param bitmap
     */
    public 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();
        zoomto(zoomdefault());
    }

    public void zoomto(float scale) {
        float width = getwidth();
        float height = getheight();

        zoomto(scale, width/2f, height/2f);
    }

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

    /**
     * 计算中心位置
     *
     * @param vertical
     * @param horizontal
     * @param animate
     */
    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());
    }

    protected void posttranslate(float dx, float dy) {
        msuppmatrix.posttranslate(dx, dy);
    }

    public float getscale() {
        return getscale(msuppmatrix);
    }

    protected float getscale(matrix matrix) {
        if(mbitmap!=null)
            return getvalue(matrix, matrix.mscale_x);
        else
            return 1f;
    }

    protected float getvalue(matrix matrix, int whichvalue) {
        matrix.getvalues(mmatrixvalues);
        return mmatrixvalues[whichvalue];
    }

    /**
     * 计算最大的拉伸比例
     *
     * @return
     */
    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;
    }

    /**
     * 原始显示比例
     *
     * @return
     */
    public 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);
    }

    protected 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();

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

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

    private float easeout( float time, float start, float end, float duration){
        return end * ( ( time = time / duration - 1 ) * time * time + 1 ) + start;
    }

    @override
    protected void ondraw(canvas canvas) {
        // todo auto-generated method stub
        if(mbitmap!=null && !mbitmap.isrecycled() ){
            if( build.version.sdk_int >=  build.version_codes.honeycomb && getlayertype() == view.layer_type_hardware ){
                canvas.drawbitmap(mbitmap, mmatrix, null);
            }else{
                if( (system.currenttimemillis()-mlastdraw) > spaintdelay ){
                    canvas.drawbitmap(mbitmap, mmatrix, mpaint);
                    mlastdraw = system.currenttimemillis();
                }
                else{
                    canvas.drawbitmap(mbitmap, mmatrix, null);
                    removecallbacks(mrefresh);
                    postdelayed(mrefresh, spaintdelay);
                }
            }
        }
    }

    /**
     * @author administrator
     *
     * 手势缩放监听
     */
    class scalelistener extends scalegesturedetector.simpleonscalegesturelistener {

        @override
        public boolean onscale(scalegesturedetector detector) {
            // todo auto-generated method stub
            log.i("zoomimageview", "onscale");
            if(detector!=null && detector.isinprogress()){
                try{
                    float targetscale = getscale() * detector.getscalefactor();
                    targetscale = math.min(maxzoom(), math.max(targetscale, 1.0f) );

                    zoomto(targetscale, detector.getfocusx(), detector.getfocusy() );
                    invalidate();
                    return true;
                }catch(illegalargumentexception e){
                    e.printstacktrace();
                }
            }
            return false;
        }
    };

    /**
     * @author administrator
     *
     * 手势识别监听
     */
    class mygesturelistener extends gesturedetector.simpleongesturelistener {

        @override
        public boolean onscroll(motionevent e1, motionevent e2,
                float distancex, float distancey) {
            // todo auto-generated method stub
            log.i("zoomimageview", "onscroll");
            if((e1 != null && e1.getpointercount() > 1) || (e2 != null && e2.getpointercount() > 1)
                    || (mscaledetector != null && mscaledetector.isinprogress())){
                return false;
            }

            if(getscale() > zoomdefault() ) {
                removecallbacks(mfling);
                posttranslate(-distancex, -distancey);
                center(true, true, false);
            }

            return true;
        }

        @override
        public boolean onfling(motionevent e1, motionevent e2, float velocityx,
                float velocityy) {
            log.i("zoomimageview", "onfling");
            // todo auto-generated method stub
            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){
                e.printstacktrace();
            }

            return super.onfling( e1, e2, velocityx, velocityy );
        }

        @override
        public boolean ondoubletap(motionevent e) {
            // todo auto-generated method stub
            log.i("zoomimageview", "ondoubletap");
            if ( getscale() > zoomdefault() ){
                zoomto(zoomdefault());
            }
            else
                zoomto(zoomdefault()*3, e.getx(), e.gety(),200);
            return true;
        }

        @override
        public boolean onsingletapconfirmed(motionevent e) {
            // todo auto-generated method stub
            log.i("zoomimageview", "onsingletapconfirmed");
            // 设置点击事件
            if(mimagetouchedlistener != null) {
                mimagetouchedlistener.onimagetouched();
                return false;
            }
            return super.onsingletapconfirmed(e);
        }

    }

    @override
    public boolean ontouchevent(motionevent event) {
        // todo auto-generated method stub
        if(mbitmap != null) {
            mscaledetector.ontouchevent(event);

            if(!mscaledetector.isinprogress()) {
                mgesturedetector.ontouchevent(event);
            }
        }

        return true;
    };

    /**
     *
     * @author administrator
     *
     * 点击接口
     */
    private onimagetouchedlistener mimagetouchedlistener;

    public interface onimagetouchedlistener {
        void onimagetouched();
    }

    public void setonimagetouchedlistener(onimagetouchedlistener listener ){
        this.mimagetouchedlistener = listener;
    }

xml布局:

复制代码 代码如下:

<com.example.pay.zoomimageview
        android:scaletype="matrix"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:id="@+id/zommimageview"
        />

activity调用方法:

复制代码 代码如下:

mzoomimageview = (zoomimageview) findviewbyid(r.id.zommimageview);
        mzoomimageview.setimagebitmap(bitmapfactory.decoderesource(getresources(), r.drawable.ic_launcher));
        mzoomimageview.setonimagetouchedlistener(new onimagetouchedlistener() {

            @override
            public void onimagetouched() {
                // todo auto-generated method stub
                toast.maketext(mainactivity.this, "11111", toast.length_long).show();
            }
        });

如对本文有疑问,请在下面进行留言讨论,广大热心网友会与你互动!! 点击进行留言回复

相关文章:

验证码:
移动技术网